Update dependencies
This commit is contained in:
parent
4c0f4cc9d9
commit
e8b1cb18d4
|
@ -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 2014 Google Inc.
|
|
||||||
|
|
||||||
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.
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 iam supports the resource-specific operations of Google Cloud
|
||||||
|
// IAM (Identity and Access Management) for the Google Cloud Libraries.
|
||||||
|
// See https://cloud.google.com/iam for more about IAM.
|
||||||
|
//
|
||||||
|
// Users of the Google Cloud Libraries will typically not use this package
|
||||||
|
// directly. Instead they will begin with some resource that supports IAM, like
|
||||||
|
// a pubsub topic, and call its IAM method to get a Handle for that resource.
|
||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
pb "google.golang.org/genproto/googleapis/iam/v1"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// client abstracts the IAMPolicy API to allow multiple implementations.
|
||||||
|
type client interface {
|
||||||
|
Get(ctx context.Context, resource string) (*pb.Policy, error)
|
||||||
|
Set(ctx context.Context, resource string, p *pb.Policy) error
|
||||||
|
Test(ctx context.Context, resource string, perms []string) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// grpcClient implements client for the standard gRPC-based IAMPolicy service.
|
||||||
|
type grpcClient struct {
|
||||||
|
c pb.IAMPolicyClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
|
||||||
|
proto, err := g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return proto, nil
|
||||||
|
}
|
||||||
|
func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
|
||||||
|
_, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
|
||||||
|
Resource: resource,
|
||||||
|
Policy: p,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
|
||||||
|
res, err := g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
|
||||||
|
Resource: resource,
|
||||||
|
Permissions: perms,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Permissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Handle provides IAM operations for a resource.
|
||||||
|
type Handle struct {
|
||||||
|
c client
|
||||||
|
resource string
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandle is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandle returns a Handle for resource.
|
||||||
|
// The conn parameter refers to a server that must support the IAMPolicy service.
|
||||||
|
func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
|
||||||
|
return InternalNewHandleClient(&grpcClient{c: pb.NewIAMPolicyClient(conn)}, resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandleClient is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandleClient returns a Handle for resource using the given
|
||||||
|
// client implementation.
|
||||||
|
func InternalNewHandleClient(c client, resource string) *Handle {
|
||||||
|
return &Handle{
|
||||||
|
c: c,
|
||||||
|
resource: resource,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Policy retrieves the IAM policy for the resource.
|
||||||
|
func (h *Handle) Policy(ctx context.Context) (*Policy, error) {
|
||||||
|
proto, err := h.c.Get(ctx, h.resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Policy{InternalProto: proto}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPolicy replaces the resource's current policy with the supplied Policy.
|
||||||
|
//
|
||||||
|
// If policy was created from a prior call to Get, then the modification will
|
||||||
|
// only succeed if the policy has not changed since the Get.
|
||||||
|
func (h *Handle) SetPolicy(ctx context.Context, policy *Policy) error {
|
||||||
|
return h.c.Set(ctx, h.resource, policy.InternalProto)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPermissions returns the subset of permissions that the caller has on the resource.
|
||||||
|
func (h *Handle) TestPermissions(ctx context.Context, permissions []string) ([]string, error) {
|
||||||
|
return h.c.Test(ctx, h.resource, permissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RoleName is a name representing a collection of permissions.
|
||||||
|
type RoleName string
|
||||||
|
|
||||||
|
// Common role names.
|
||||||
|
const (
|
||||||
|
Owner RoleName = "roles/owner"
|
||||||
|
Editor RoleName = "roles/editor"
|
||||||
|
Viewer RoleName = "roles/viewer"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AllUsers is a special member that denotes all users, even unauthenticated ones.
|
||||||
|
AllUsers = "allUsers"
|
||||||
|
|
||||||
|
// AllAuthenticatedUsers is a special member that denotes all authenticated users.
|
||||||
|
AllAuthenticatedUsers = "allAuthenticatedUsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Policy is a list of Bindings representing roles
|
||||||
|
// granted to members.
|
||||||
|
//
|
||||||
|
// The zero Policy is a valid policy with no bindings.
|
||||||
|
type Policy struct {
|
||||||
|
// TODO(jba): when type aliases are available, put Policy into an internal package
|
||||||
|
// and provide an exported alias here.
|
||||||
|
|
||||||
|
// This field is exported for use by the Google Cloud Libraries only.
|
||||||
|
// It may become unexported in a future release.
|
||||||
|
InternalProto *pb.Policy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members returns the list of members with the supplied role.
|
||||||
|
// The return value should not be modified. Use Add and Remove
|
||||||
|
// to modify the members of a role.
|
||||||
|
func (p *Policy) Members(r RoleName) []string {
|
||||||
|
b := p.binding(r)
|
||||||
|
if b == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return b.Members
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasRole reports whether member has role r.
|
||||||
|
func (p *Policy) HasRole(member string, r RoleName) bool {
|
||||||
|
return memberIndex(member, p.binding(r)) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds member member to role r if it is not already present.
|
||||||
|
// A new binding is created if there is no binding for the role.
|
||||||
|
func (p *Policy) Add(member string, r RoleName) {
|
||||||
|
b := p.binding(r)
|
||||||
|
if b == nil {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
p.InternalProto = &pb.Policy{}
|
||||||
|
}
|
||||||
|
p.InternalProto.Bindings = append(p.InternalProto.Bindings, &pb.Binding{
|
||||||
|
Role: string(r),
|
||||||
|
Members: []string{member},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if memberIndex(member, b) < 0 {
|
||||||
|
b.Members = append(b.Members, member)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes member from role r if it is present.
|
||||||
|
func (p *Policy) Remove(member string, r RoleName) {
|
||||||
|
bi := p.bindingIndex(r)
|
||||||
|
if bi < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bindings := p.InternalProto.Bindings
|
||||||
|
b := bindings[bi]
|
||||||
|
mi := memberIndex(member, b)
|
||||||
|
if mi < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Order doesn't matter for bindings or members, so to remove, move the last item
|
||||||
|
// into the removed spot and shrink the slice.
|
||||||
|
if len(b.Members) == 1 {
|
||||||
|
// Remove binding.
|
||||||
|
last := len(bindings) - 1
|
||||||
|
bindings[bi] = bindings[last]
|
||||||
|
bindings[last] = nil
|
||||||
|
p.InternalProto.Bindings = bindings[:last]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Remove member.
|
||||||
|
// TODO(jba): worry about multiple copies of m?
|
||||||
|
last := len(b.Members) - 1
|
||||||
|
b.Members[mi] = b.Members[last]
|
||||||
|
b.Members[last] = ""
|
||||||
|
b.Members = b.Members[:last]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roles returns the names of all the roles that appear in the Policy.
|
||||||
|
func (p *Policy) Roles() []RoleName {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var rns []RoleName
|
||||||
|
for _, b := range p.InternalProto.Bindings {
|
||||||
|
rns = append(rns, RoleName(b.Role))
|
||||||
|
}
|
||||||
|
return rns
|
||||||
|
}
|
||||||
|
|
||||||
|
// binding returns the Binding for the suppied role, or nil if there isn't one.
|
||||||
|
func (p *Policy) binding(r RoleName) *pb.Binding {
|
||||||
|
i := p.bindingIndex(r)
|
||||||
|
if i < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.InternalProto.Bindings[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Policy) bindingIndex(r RoleName) int {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i, b := range p.InternalProto.Bindings {
|
||||||
|
if b.Role == string(r) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// memberIndex returns the index of m in b's Members, or -1 if not found.
|
||||||
|
func memberIndex(m string, b *pb.Binding) int {
|
||||||
|
if b == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i, mm := range b.Members {
|
||||||
|
if mm == m {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Annotate prepends msg to the error message in err, attempting
|
||||||
|
// to preserve other information in err, like an error code.
|
||||||
|
//
|
||||||
|
// Annotate panics if err is nil.
|
||||||
|
//
|
||||||
|
// Annotate knows about these error types:
|
||||||
|
// - "google.golang.org/grpc/status".Status
|
||||||
|
// - "google.golang.org/api/googleapi".Error
|
||||||
|
// If the error is not one of these types, Annotate behaves
|
||||||
|
// like
|
||||||
|
// fmt.Errorf("%s: %v", msg, err)
|
||||||
|
func Annotate(err error, msg string) error {
|
||||||
|
if err == nil {
|
||||||
|
panic("Annotate called with nil")
|
||||||
|
}
|
||||||
|
if s, ok := status.FromError(err); ok {
|
||||||
|
p := s.Proto()
|
||||||
|
p.Message = msg + ": " + p.Message
|
||||||
|
return status.ErrorProto(p)
|
||||||
|
}
|
||||||
|
if g, ok := err.(*googleapi.Error); ok {
|
||||||
|
g.Message = msg + ": " + g.Message
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s: %v", msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef uses format and args to format a string, then calls Annotate.
|
||||||
|
func Annotatef(err error, format string, args ...interface{}) error {
|
||||||
|
return Annotate(err, fmt.Sprintf(format, args...))
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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 internal provides support for the cloud packages.
|
|
||||||
//
|
|
||||||
// Users should not import this package directly.
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
const userAgent = "gcloud-golang/0.1"
|
|
||||||
|
|
||||||
// Transport is an http.RoundTripper that appends Google Cloud client's
|
|
||||||
// user-agent to the original request's user-agent header.
|
|
||||||
type Transport struct {
|
|
||||||
// TODO(bradfitz): delete internal.Transport. It's too wrappy for what it does.
|
|
||||||
// Do User-Agent some other way.
|
|
||||||
|
|
||||||
// Base is the actual http.RoundTripper
|
|
||||||
// requests will use. It must not be nil.
|
|
||||||
Base http.RoundTripper
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundTrip appends a user-agent to the existing user-agent
|
|
||||||
// header and delegates the request to the base http.RoundTripper.
|
|
||||||
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
req = cloneRequest(req)
|
|
||||||
ua := req.Header.Get("User-Agent")
|
|
||||||
if ua == "" {
|
|
||||||
ua = userAgent
|
|
||||||
} else {
|
|
||||||
ua = fmt.Sprintf("%s %s", ua, userAgent)
|
|
||||||
}
|
|
||||||
req.Header.Set("User-Agent", ua)
|
|
||||||
return t.Base.RoundTrip(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
for k, s := range r.Header {
|
|
||||||
r2.Header[k] = s
|
|
||||||
}
|
|
||||||
return r2
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ package optional
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -37,6 +38,9 @@ type (
|
||||||
|
|
||||||
// Float64 is either a float64 or nil.
|
// Float64 is either a float64 or nil.
|
||||||
Float64 interface{}
|
Float64 interface{}
|
||||||
|
|
||||||
|
// Duration is either a time.Duration or nil.
|
||||||
|
Duration interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToBool returns its argument as a bool.
|
// ToBool returns its argument as a bool.
|
||||||
|
@ -89,6 +93,16 @@ func ToFloat64(v Float64) float64 {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToDuration returns its argument as a time.Duration.
|
||||||
|
// It panics if its argument is nil or not a time.Duration.
|
||||||
|
func ToDuration(v Duration) time.Duration {
|
||||||
|
x, ok := v.(time.Duration)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Duration", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
func doPanic(capType string, v interface{}) {
|
func doPanic(capType string, v interface{}) {
|
||||||
panic(fmt.Sprintf("optional.%s value should be %s, got %T", capType, strings.ToLower(capType), v))
|
panic(fmt.Sprintf("optional.%s value should be %s, got %T", capType, strings.ToLower(capType), v))
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gax "github.com/googleapis/gax-go"
|
gax "github.com/googleapis/gax-go"
|
||||||
|
@ -27,7 +26,8 @@ import (
|
||||||
// backoff parameters. It returns when one of the following occurs:
|
// backoff parameters. It returns when one of the following occurs:
|
||||||
// When f's first return value is true, Retry immediately returns with f's second
|
// When f's first return value is true, Retry immediately returns with f's second
|
||||||
// return value.
|
// return value.
|
||||||
// When the provided context is done, Retry returns with ctx.Err().
|
// When the provided context is done, Retry returns with an error that
|
||||||
|
// includes both ctx.Error() and the last error returned by f.
|
||||||
func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
|
func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
|
||||||
return retry(ctx, bo, f, gax.Sleep)
|
return retry(ctx, bo, f, gax.Sleep)
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
|
||||||
p := bo.Pause()
|
p := bo.Pause()
|
||||||
if cerr := sleep(ctx, p); cerr != nil {
|
if cerr := sleep(ctx, p); cerr != nil {
|
||||||
if lastErr != nil {
|
if lastErr != nil {
|
||||||
return fmt.Errorf("%v; last function err: %v", cerr, lastErr)
|
return Annotatef(lastErr, "retry failed with %v; last error", cerr)
|
||||||
}
|
}
|
||||||
return cerr
|
return cerr
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
today=$(date +%Y%m%d)
|
||||||
|
|
||||||
|
sed -i -r -e 's/const Repo = "([0-9]{8})"/const Repo = "'$today'"/' $GOFILE
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:generate ./update_version.sh
|
||||||
|
|
||||||
|
// Package version contains version information for Google Cloud Client
|
||||||
|
// Libraries for Go, as reported in request headers.
|
||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Repo is the current version of the client libraries in this
|
||||||
|
// repo. It should be a date in YYYYMMDD format.
|
||||||
|
const Repo = "20170928"
|
||||||
|
|
||||||
|
// Go returns the Go runtime version. The returned string
|
||||||
|
// has no whitespace.
|
||||||
|
func Go() string {
|
||||||
|
return goVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
var goVersion = goVer(runtime.Version())
|
||||||
|
|
||||||
|
const develPrefix = "devel +"
|
||||||
|
|
||||||
|
func goVer(s string) string {
|
||||||
|
if strings.HasPrefix(s, develPrefix) {
|
||||||
|
s = s[len(develPrefix):]
|
||||||
|
if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
|
||||||
|
s = s[:p]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(s, "go1") {
|
||||||
|
s = s[2:]
|
||||||
|
var prerelease string
|
||||||
|
if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
|
||||||
|
s, prerelease = s[:p], s[p:]
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(s, ".") {
|
||||||
|
s += "0"
|
||||||
|
} else if strings.Count(s, ".") < 2 {
|
||||||
|
s += ".0"
|
||||||
|
}
|
||||||
|
if prerelease != "" {
|
||||||
|
s += "-" + prerelease
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func notSemverRune(r rune) bool {
|
||||||
|
return strings.IndexRune("0123456789.", r) < 0
|
||||||
|
}
|
|
@ -15,9 +15,11 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ type ACLRole string
|
||||||
const (
|
const (
|
||||||
RoleOwner ACLRole = "OWNER"
|
RoleOwner ACLRole = "OWNER"
|
||||||
RoleReader ACLRole = "READER"
|
RoleReader ACLRole = "READER"
|
||||||
|
RoleWriter ACLRole = "WRITER"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ACLEntity refers to a user or group.
|
// ACLEntity refers to a user or group.
|
||||||
|
@ -56,6 +59,7 @@ type ACLHandle struct {
|
||||||
bucket string
|
bucket string
|
||||||
object string
|
object string
|
||||||
isDefault bool
|
isDefault bool
|
||||||
|
userProject string // for requester-pays buckets
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete permanently deletes the ACL entry for the given entity.
|
// Delete permanently deletes the ACL entry for the given entity.
|
||||||
|
@ -72,10 +76,10 @@ func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) error {
|
||||||
// Set sets the permission level for the given entity.
|
// Set sets the permission level for the given entity.
|
||||||
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
||||||
if a.object != "" {
|
if a.object != "" {
|
||||||
return a.objectSet(ctx, entity, role)
|
return a.objectSet(ctx, entity, role, false)
|
||||||
}
|
}
|
||||||
if a.isDefault {
|
if a.isDefault {
|
||||||
return a.bucketDefaultSet(ctx, entity, role)
|
return a.objectSet(ctx, entity, role, true)
|
||||||
}
|
}
|
||||||
return a.bucketSet(ctx, entity, role)
|
return a.bucketSet(ctx, entity, role)
|
||||||
}
|
}
|
||||||
|
@ -95,50 +99,36 @@ func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
|
||||||
var acls *raw.ObjectAccessControls
|
var acls *raw.ObjectAccessControls
|
||||||
var err error
|
var err error
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
acls, err = a.c.raw.DefaultObjectAccessControls.List(a.bucket).Context(ctx).Do()
|
req := a.c.raw.DefaultObjectAccessControls.List(a.bucket)
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
acls, err = req.Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("storage: error listing default object ACL for bucket %q: %v", a.bucket, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return toACLRules(acls.Items), nil
|
return toACLRules(acls.Items), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACLHandle) bucketDefaultSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
|
||||||
acl := &raw.ObjectAccessControl{
|
|
||||||
Bucket: a.bucket,
|
|
||||||
Entity: string(entity),
|
|
||||||
Role: string(role),
|
|
||||||
}
|
|
||||||
err := runWithRetry(ctx, func() error {
|
|
||||||
_, err := a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl).Context(ctx).Do()
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("storage: error updating default ACL entry for bucket %q, entity %q: %v", a.bucket, entity, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
|
func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
err := runWithRetry(ctx, func() error {
|
return runWithRetry(ctx, func() error {
|
||||||
return a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity)).Context(ctx).Do()
|
req := a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity))
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
return req.Do()
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("storage: error deleting default ACL entry for bucket %q, entity %q: %v", a.bucket, entity, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
|
func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
|
||||||
var acls *raw.BucketAccessControls
|
var acls *raw.BucketAccessControls
|
||||||
var err error
|
var err error
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
acls, err = a.c.raw.BucketAccessControls.List(a.bucket).Context(ctx).Do()
|
req := a.c.raw.BucketAccessControls.List(a.bucket)
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
acls, err = req.Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("storage: error listing bucket ACL for bucket %q: %v", a.bucket, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
r := make([]ACLRule, len(acls.Items))
|
r := make([]ACLRule, len(acls.Items))
|
||||||
for i, v := range acls.Items {
|
for i, v := range acls.Items {
|
||||||
|
@ -155,21 +145,25 @@ func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRol
|
||||||
Role: string(role),
|
Role: string(role),
|
||||||
}
|
}
|
||||||
err := runWithRetry(ctx, func() error {
|
err := runWithRetry(ctx, func() error {
|
||||||
_, err := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl).Context(ctx).Do()
|
req := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl)
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
_, err := req.Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("storage: error updating bucket ACL entry for bucket %q, entity %q: %v", a.bucket, entity, err)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
|
func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
err := runWithRetry(ctx, func() error {
|
err := runWithRetry(ctx, func() error {
|
||||||
return a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity)).Context(ctx).Do()
|
req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity))
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
return req.Do()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("storage: error deleting bucket ACL entry for bucket %q, entity %q: %v", a.bucket, entity, err)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -178,39 +172,58 @@ func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
|
||||||
var acls *raw.ObjectAccessControls
|
var acls *raw.ObjectAccessControls
|
||||||
var err error
|
var err error
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
acls, err = a.c.raw.ObjectAccessControls.List(a.bucket, a.object).Context(ctx).Do()
|
req := a.c.raw.ObjectAccessControls.List(a.bucket, a.object)
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
acls, err = req.Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("storage: error listing object ACL for bucket %q, file %q: %v", a.bucket, a.object, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return toACLRules(acls.Items), nil
|
return toACLRules(acls.Items), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
|
||||||
|
type setRequest interface {
|
||||||
|
Do(opts ...googleapi.CallOption) (*raw.ObjectAccessControl, error)
|
||||||
|
Header() http.Header
|
||||||
|
}
|
||||||
|
|
||||||
acl := &raw.ObjectAccessControl{
|
acl := &raw.ObjectAccessControl{
|
||||||
Bucket: a.bucket,
|
Bucket: a.bucket,
|
||||||
Entity: string(entity),
|
Entity: string(entity),
|
||||||
Role: string(role),
|
Role: string(role),
|
||||||
}
|
}
|
||||||
err := runWithRetry(ctx, func() error {
|
var req setRequest
|
||||||
_, err := a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl).Context(ctx).Do()
|
if isBucketDefault {
|
||||||
|
req = a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl)
|
||||||
|
} else {
|
||||||
|
req = a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl)
|
||||||
|
}
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
_, err := req.Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("storage: error updating object ACL entry for bucket %q, file %q, entity %q: %v", a.bucket, a.object, entity, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
|
func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
err := runWithRetry(ctx, func() error {
|
return runWithRetry(ctx, func() error {
|
||||||
return a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity)).Context(ctx).Do()
|
req := a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity))
|
||||||
|
a.configureCall(req, ctx)
|
||||||
|
return req.Do()
|
||||||
})
|
})
|
||||||
if err != nil {
|
}
|
||||||
return fmt.Errorf("storage: error deleting object ACL entry for bucket %q, file %q, entity %q: %v", a.bucket, a.object, entity, err)
|
|
||||||
|
func (a *ACLHandle) configureCall(call interface {
|
||||||
|
Header() http.Header
|
||||||
|
}, ctx context.Context) {
|
||||||
|
vc := reflect.ValueOf(call)
|
||||||
|
vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
|
||||||
|
if a.userProject != "" {
|
||||||
|
vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
|
||||||
}
|
}
|
||||||
return nil
|
setClientHeader(call.Header())
|
||||||
}
|
}
|
||||||
|
|
||||||
func toACLRules(items []*raw.ObjectAccessControl) []ACLRule {
|
func toACLRules(items []*raw.ObjectAccessControl) []ACLRule {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
// Copyright 2014 Google Inc. LiveAndArchived Rights Reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -15,15 +15,52 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/optional"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BucketHandle provides operations on a Google Cloud Storage bucket.
|
||||||
|
// Use Client.Bucket to get a handle.
|
||||||
|
type BucketHandle struct {
|
||||||
|
c *Client
|
||||||
|
name string
|
||||||
|
acl ACLHandle
|
||||||
|
defaultObjectACL ACLHandle
|
||||||
|
conds *BucketConditions
|
||||||
|
userProject string // project for Requester Pays buckets
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucket returns a BucketHandle, which provides operations on the named bucket.
|
||||||
|
// This call does not perform any network operations.
|
||||||
|
//
|
||||||
|
// The supplied name must contain only lowercase letters, numbers, dashes,
|
||||||
|
// underscores, and dots. The full specification for valid bucket names can be
|
||||||
|
// found at:
|
||||||
|
// https://cloud.google.com/storage/docs/bucket-naming
|
||||||
|
func (c *Client) Bucket(name string) *BucketHandle {
|
||||||
|
return &BucketHandle{
|
||||||
|
c: c,
|
||||||
|
name: name,
|
||||||
|
acl: ACLHandle{
|
||||||
|
c: c,
|
||||||
|
bucket: name,
|
||||||
|
},
|
||||||
|
defaultObjectACL: ACLHandle{
|
||||||
|
c: c,
|
||||||
|
bucket: name,
|
||||||
|
isDefault: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create creates the Bucket in the project.
|
// Create creates the Bucket in the project.
|
||||||
// If attrs is nil the API defaults will be used.
|
// If attrs is nil the API defaults will be used.
|
||||||
func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) error {
|
func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) error {
|
||||||
|
@ -34,16 +71,37 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck
|
||||||
bkt = &raw.Bucket{}
|
bkt = &raw.Bucket{}
|
||||||
}
|
}
|
||||||
bkt.Name = b.name
|
bkt.Name = b.name
|
||||||
|
// If there is lifecycle information but no location, explicitly set
|
||||||
|
// the location. This is a GCS quirk/bug.
|
||||||
|
if bkt.Location == "" && bkt.Lifecycle != nil {
|
||||||
|
bkt.Location = "US"
|
||||||
|
}
|
||||||
req := b.c.raw.Buckets.Insert(projectID, bkt)
|
req := b.c.raw.Buckets.Insert(projectID, bkt)
|
||||||
|
setClientHeader(req.Header())
|
||||||
return runWithRetry(ctx, func() error { _, err := req.Context(ctx).Do(); return err })
|
return runWithRetry(ctx, func() error { _, err := req.Context(ctx).Do(); return err })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the Bucket.
|
// Delete deletes the Bucket.
|
||||||
func (b *BucketHandle) Delete(ctx context.Context) error {
|
func (b *BucketHandle) Delete(ctx context.Context) error {
|
||||||
req := b.c.raw.Buckets.Delete(b.name)
|
req, err := b.newDeleteCall()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return runWithRetry(ctx, func() error { return req.Context(ctx).Do() })
|
return runWithRetry(ctx, func() error { return req.Context(ctx).Do() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BucketHandle) newDeleteCall() (*raw.BucketsDeleteCall, error) {
|
||||||
|
req := b.c.raw.Buckets.Delete(b.name)
|
||||||
|
setClientHeader(req.Header())
|
||||||
|
if err := applyBucketConds("BucketHandle.Delete", b.conds, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if b.userProject != "" {
|
||||||
|
req.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ACL returns an ACLHandle, which provides access to the bucket's access control list.
|
// ACL returns an ACLHandle, which provides access to the bucket's access control list.
|
||||||
// This controls who can list, create or overwrite the objects in a bucket.
|
// This controls who can list, create or overwrite the objects in a bucket.
|
||||||
// This call does not perform any network operations.
|
// This call does not perform any network operations.
|
||||||
|
@ -73,17 +131,22 @@ func (b *BucketHandle) Object(name string) *ObjectHandle {
|
||||||
c: b.c,
|
c: b.c,
|
||||||
bucket: b.name,
|
bucket: b.name,
|
||||||
object: name,
|
object: name,
|
||||||
|
userProject: b.userProject,
|
||||||
},
|
},
|
||||||
gen: -1,
|
gen: -1,
|
||||||
|
userProject: b.userProject,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attrs returns the metadata for the bucket.
|
// Attrs returns the metadata for the bucket.
|
||||||
func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
||||||
|
req, err := b.newGetCall()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var resp *raw.Bucket
|
var resp *raw.Bucket
|
||||||
var err error
|
|
||||||
err = runWithRetry(ctx, func() error {
|
err = runWithRetry(ctx, func() error {
|
||||||
resp, err = b.c.raw.Buckets.Get(b.name).Projection("full").Context(ctx).Do()
|
resp, err = req.Context(ctx).Do()
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||||
|
@ -95,9 +158,49 @@ func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
|
||||||
return newBucket(resp), nil
|
return newBucket(resp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
|
||||||
|
req := b.c.raw.Buckets.Get(b.name).Projection("full")
|
||||||
|
setClientHeader(req.Header())
|
||||||
|
if err := applyBucketConds("BucketHandle.Attrs", b.conds, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if b.userProject != "" {
|
||||||
|
req.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (*BucketAttrs, error) {
|
||||||
|
req, err := b.newPatchCall(&uattrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// TODO(jba): retry iff metagen is set?
|
||||||
|
rb, err := req.Context(ctx).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newBucket(rb), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BucketHandle) newPatchCall(uattrs *BucketAttrsToUpdate) (*raw.BucketsPatchCall, error) {
|
||||||
|
rb := uattrs.toRawBucket()
|
||||||
|
req := b.c.raw.Buckets.Patch(b.name, rb).Projection("full")
|
||||||
|
setClientHeader(req.Header())
|
||||||
|
if err := applyBucketConds("BucketHandle.Update", b.conds, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if b.userProject != "" {
|
||||||
|
req.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BucketAttrs represents the metadata for a Google Cloud Storage bucket.
|
// BucketAttrs represents the metadata for a Google Cloud Storage bucket.
|
||||||
|
// Read-only fields are ignored by BucketHandle.Create.
|
||||||
type BucketAttrs struct {
|
type BucketAttrs struct {
|
||||||
// Name is the name of the bucket.
|
// Name is the name of the bucket.
|
||||||
|
// This field is read-only.
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// ACL is the list of access control rules on the bucket.
|
// ACL is the list of access control rules on the bucket.
|
||||||
|
@ -111,9 +214,10 @@ type BucketAttrs struct {
|
||||||
Location string
|
Location string
|
||||||
|
|
||||||
// MetaGeneration is the metadata generation of the bucket.
|
// MetaGeneration is the metadata generation of the bucket.
|
||||||
|
// This field is read-only.
|
||||||
MetaGeneration int64
|
MetaGeneration int64
|
||||||
|
|
||||||
// StorageClass is the storage class of the bucket. This defines
|
// StorageClass is the default storage class of the bucket. This defines
|
||||||
// how objects in the bucket are stored and determines the SLA
|
// how objects in the bucket are stored and determines the SLA
|
||||||
// and the cost of storage. Typical values are "MULTI_REGIONAL",
|
// and the cost of storage. Typical values are "MULTI_REGIONAL",
|
||||||
// "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD" and
|
// "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD" and
|
||||||
|
@ -123,11 +227,112 @@ type BucketAttrs struct {
|
||||||
StorageClass string
|
StorageClass string
|
||||||
|
|
||||||
// Created is the creation time of the bucket.
|
// Created is the creation time of the bucket.
|
||||||
|
// This field is read-only.
|
||||||
Created time.Time
|
Created time.Time
|
||||||
|
|
||||||
// VersioningEnabled reports whether this bucket has versioning enabled.
|
// VersioningEnabled reports whether this bucket has versioning enabled.
|
||||||
// This field is read-only.
|
|
||||||
VersioningEnabled bool
|
VersioningEnabled bool
|
||||||
|
|
||||||
|
// Labels are the bucket's labels.
|
||||||
|
Labels map[string]string
|
||||||
|
|
||||||
|
// RequesterPays reports whether the bucket is a Requester Pays bucket.
|
||||||
|
// Clients performing operations on Requester Pays buckets must provide
|
||||||
|
// a user project (see BucketHandle.UserProject), which will be billed
|
||||||
|
// for the operations.
|
||||||
|
RequesterPays bool
|
||||||
|
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
||||||
|
Lifecycle Lifecycle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lifecycle is the lifecycle configuration for objects in the bucket.
|
||||||
|
type Lifecycle struct {
|
||||||
|
Rules []LifecycleRule
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
|
||||||
|
rfc3339Date = "2006-01-02"
|
||||||
|
|
||||||
|
// DeleteAction is a lifecycle action that deletes a live and/or archived
|
||||||
|
// objects. Takes precendence over SetStorageClass actions.
|
||||||
|
DeleteAction = "Delete"
|
||||||
|
|
||||||
|
// SetStorageClassAction changes the storage class of live and/or archived
|
||||||
|
// objects.
|
||||||
|
SetStorageClassAction = "SetStorageClass"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LifecycleRule is a lifecycle configuration rule.
|
||||||
|
//
|
||||||
|
// When all the configured conditions are met by an object in the bucket, the
|
||||||
|
// configured action will automatically be taken on that object.
|
||||||
|
type LifecycleRule struct {
|
||||||
|
// Action is the action to take when all of the associated conditions are
|
||||||
|
// met.
|
||||||
|
Action LifecycleAction
|
||||||
|
|
||||||
|
// Condition is the set of conditions that must be met for the associated
|
||||||
|
// action to be taken.
|
||||||
|
Condition LifecycleCondition
|
||||||
|
}
|
||||||
|
|
||||||
|
// LifecycleAction is a lifecycle configuration action.
|
||||||
|
type LifecycleAction struct {
|
||||||
|
// Type is the type of action to take on matching objects.
|
||||||
|
//
|
||||||
|
// Acceptable values are "Delete" to delete matching objects and
|
||||||
|
// "SetStorageClass" to set the storage class defined in StorageClass on
|
||||||
|
// matching objects.
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// StorageClass is the storage class to set on matching objects if the Action
|
||||||
|
// is "SetStorageClass".
|
||||||
|
StorageClass string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liveness specifies whether the object is live or not.
|
||||||
|
type Liveness int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LiveAndArchived includes both live and archived objects.
|
||||||
|
LiveAndArchived Liveness = iota
|
||||||
|
// Live specifies that the object is still live.
|
||||||
|
Live
|
||||||
|
// Archived specifies that the object is archived.
|
||||||
|
Archived
|
||||||
|
)
|
||||||
|
|
||||||
|
// LifecycleCondition is a set of conditions used to match objects and take an
|
||||||
|
// action automatically.
|
||||||
|
//
|
||||||
|
// All configured conditions must be met for the associated action to be taken.
|
||||||
|
type LifecycleCondition struct {
|
||||||
|
// AgeInDays is the age of the object in days.
|
||||||
|
AgeInDays int64
|
||||||
|
|
||||||
|
// CreatedBefore is the time the object was created.
|
||||||
|
//
|
||||||
|
// This condition is satisfied when an object is created before midnight of
|
||||||
|
// the specified date in UTC.
|
||||||
|
CreatedBefore time.Time
|
||||||
|
|
||||||
|
// Liveness specifies the object's liveness. Relevant only for versioned objects
|
||||||
|
Liveness Liveness
|
||||||
|
|
||||||
|
// MatchesStorageClasses is the condition matching the object's storage
|
||||||
|
// class.
|
||||||
|
//
|
||||||
|
// Values include "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE",
|
||||||
|
// "STANDARD", and "DURABLE_REDUCED_AVAILABILITY".
|
||||||
|
MatchesStorageClasses []string
|
||||||
|
|
||||||
|
// NumNewerVersions is the condition matching objects with a number of newer versions.
|
||||||
|
//
|
||||||
|
// If the value is N, this condition is satisfied when there are at least N
|
||||||
|
// versions (including the live version) newer than this version of the
|
||||||
|
// object.
|
||||||
|
NumNewerVersions int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBucket(b *raw.Bucket) *BucketAttrs {
|
func newBucket(b *raw.Bucket) *BucketAttrs {
|
||||||
|
@ -141,6 +346,9 @@ func newBucket(b *raw.Bucket) *BucketAttrs {
|
||||||
StorageClass: b.StorageClass,
|
StorageClass: b.StorageClass,
|
||||||
Created: convertTime(b.TimeCreated),
|
Created: convertTime(b.TimeCreated),
|
||||||
VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
|
VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
|
||||||
|
Labels: b.Labels,
|
||||||
|
RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
|
||||||
|
Lifecycle: toLifecycle(b.Lifecycle),
|
||||||
}
|
}
|
||||||
acl := make([]ACLRule, len(b.Acl))
|
acl := make([]ACLRule, len(b.Acl))
|
||||||
for i, rule := range b.Acl {
|
for i, rule := range b.Acl {
|
||||||
|
@ -174,15 +382,238 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dACL := toRawObjectACL(b.DefaultObjectACL)
|
dACL := toRawObjectACL(b.DefaultObjectACL)
|
||||||
|
// Copy label map.
|
||||||
|
var labels map[string]string
|
||||||
|
if len(b.Labels) > 0 {
|
||||||
|
labels = make(map[string]string, len(b.Labels))
|
||||||
|
for k, v := range b.Labels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ignore VersioningEnabled if it is false. This is OK because
|
||||||
|
// we only call this method when creating a bucket, and by default
|
||||||
|
// new buckets have versioning off.
|
||||||
|
var v *raw.BucketVersioning
|
||||||
|
if b.VersioningEnabled {
|
||||||
|
v = &raw.BucketVersioning{Enabled: true}
|
||||||
|
}
|
||||||
|
var bb *raw.BucketBilling
|
||||||
|
if b.RequesterPays {
|
||||||
|
bb = &raw.BucketBilling{RequesterPays: true}
|
||||||
|
}
|
||||||
return &raw.Bucket{
|
return &raw.Bucket{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
DefaultObjectAcl: dACL,
|
DefaultObjectAcl: dACL,
|
||||||
Location: b.Location,
|
Location: b.Location,
|
||||||
StorageClass: b.StorageClass,
|
StorageClass: b.StorageClass,
|
||||||
Acl: acl,
|
Acl: acl,
|
||||||
|
Versioning: v,
|
||||||
|
Labels: labels,
|
||||||
|
Billing: bb,
|
||||||
|
Lifecycle: toRawLifecycle(b.Lifecycle),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BucketAttrsToUpdate struct {
|
||||||
|
// VersioningEnabled, if set, updates whether the bucket uses versioning.
|
||||||
|
VersioningEnabled optional.Bool
|
||||||
|
|
||||||
|
// RequesterPays, if set, updates whether the bucket is a Requester Pays bucket.
|
||||||
|
RequesterPays optional.Bool
|
||||||
|
|
||||||
|
setLabels map[string]string
|
||||||
|
deleteLabels map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLabel causes a label to be added or modified when ua is used
|
||||||
|
// in a call to Bucket.Update.
|
||||||
|
func (ua *BucketAttrsToUpdate) SetLabel(name, value string) {
|
||||||
|
if ua.setLabels == nil {
|
||||||
|
ua.setLabels = map[string]string{}
|
||||||
|
}
|
||||||
|
ua.setLabels[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteLabel causes a label to be deleted when ua is used in a
|
||||||
|
// call to Bucket.Update.
|
||||||
|
func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
|
||||||
|
if ua.deleteLabels == nil {
|
||||||
|
ua.deleteLabels = map[string]bool{}
|
||||||
|
}
|
||||||
|
ua.deleteLabels[name] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
|
||||||
|
rb := &raw.Bucket{}
|
||||||
|
if ua.VersioningEnabled != nil {
|
||||||
|
rb.Versioning = &raw.BucketVersioning{
|
||||||
|
Enabled: optional.ToBool(ua.VersioningEnabled),
|
||||||
|
ForceSendFields: []string{"Enabled"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ua.RequesterPays != nil {
|
||||||
|
rb.Billing = &raw.BucketBilling{
|
||||||
|
RequesterPays: optional.ToBool(ua.RequesterPays),
|
||||||
|
ForceSendFields: []string{"RequesterPays"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ua.setLabels != nil || ua.deleteLabels != nil {
|
||||||
|
rb.Labels = map[string]string{}
|
||||||
|
for k, v := range ua.setLabels {
|
||||||
|
rb.Labels[k] = v
|
||||||
|
}
|
||||||
|
if len(rb.Labels) == 0 && len(ua.deleteLabels) > 0 {
|
||||||
|
rb.ForceSendFields = append(rb.ForceSendFields, "Labels")
|
||||||
|
}
|
||||||
|
for l := range ua.deleteLabels {
|
||||||
|
rb.NullFields = append(rb.NullFields, "Labels."+l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// If returns a new BucketHandle that applies a set of preconditions.
|
||||||
|
// Preconditions already set on the BucketHandle are ignored.
|
||||||
|
// Operations on the new handle will only occur if the preconditions are
|
||||||
|
// satisfied. The only valid preconditions for buckets are MetagenerationMatch
|
||||||
|
// and MetagenerationNotMatch.
|
||||||
|
func (b *BucketHandle) If(conds BucketConditions) *BucketHandle {
|
||||||
|
b2 := *b
|
||||||
|
b2.conds = &conds
|
||||||
|
return &b2
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketConditions constrain bucket methods to act on specific metagenerations.
|
||||||
|
//
|
||||||
|
// The zero value is an empty set of constraints.
|
||||||
|
type BucketConditions struct {
|
||||||
|
// MetagenerationMatch specifies that the bucket must have the given
|
||||||
|
// metageneration for the operation to occur.
|
||||||
|
// If MetagenerationMatch is zero, it has no effect.
|
||||||
|
MetagenerationMatch int64
|
||||||
|
|
||||||
|
// MetagenerationNotMatch specifies that the bucket must not have the given
|
||||||
|
// metageneration for the operation to occur.
|
||||||
|
// If MetagenerationNotMatch is zero, it has no effect.
|
||||||
|
MetagenerationNotMatch int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BucketConditions) validate(method string) error {
|
||||||
|
if *c == (BucketConditions{}) {
|
||||||
|
return fmt.Errorf("storage: %s: empty conditions", method)
|
||||||
|
}
|
||||||
|
if c.MetagenerationMatch != 0 && c.MetagenerationNotMatch != 0 {
|
||||||
|
return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserProject returns a new BucketHandle that passes the project ID as the user
|
||||||
|
// project for all subsequent calls. Calls with a user project will be billed to that
|
||||||
|
// project rather than to the bucket's owning project.
|
||||||
|
//
|
||||||
|
// A user project is required for all operations on Requester Pays buckets.
|
||||||
|
func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
|
||||||
|
b2 := *b
|
||||||
|
b2.userProject = projectID
|
||||||
|
b2.acl.userProject = projectID
|
||||||
|
b2.defaultObjectACL.userProject = projectID
|
||||||
|
return &b2
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyBucketConds modifies the provided call using the conditions in conds.
|
||||||
|
// call is something that quacks like a *raw.WhateverCall.
|
||||||
|
func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
|
||||||
|
if conds == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := conds.validate(method); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cval := reflect.ValueOf(call)
|
||||||
|
switch {
|
||||||
|
case conds.MetagenerationMatch != 0:
|
||||||
|
if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
|
||||||
|
return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
|
||||||
|
}
|
||||||
|
case conds.MetagenerationNotMatch != 0:
|
||||||
|
if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
|
||||||
|
return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
|
||||||
|
var rl raw.BucketLifecycle
|
||||||
|
if len(l.Rules) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, r := range l.Rules {
|
||||||
|
rr := &raw.BucketLifecycleRule{
|
||||||
|
Action: &raw.BucketLifecycleRuleAction{
|
||||||
|
Type: r.Action.Type,
|
||||||
|
StorageClass: r.Action.StorageClass,
|
||||||
|
},
|
||||||
|
Condition: &raw.BucketLifecycleRuleCondition{
|
||||||
|
Age: r.Condition.AgeInDays,
|
||||||
|
MatchesStorageClass: r.Condition.MatchesStorageClasses,
|
||||||
|
NumNewerVersions: r.Condition.NumNewerVersions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Condition.Liveness {
|
||||||
|
case LiveAndArchived:
|
||||||
|
rr.Condition.IsLive = nil
|
||||||
|
case Live:
|
||||||
|
rr.Condition.IsLive = googleapi.Bool(true)
|
||||||
|
case Archived:
|
||||||
|
rr.Condition.IsLive = googleapi.Bool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.Condition.CreatedBefore.IsZero() {
|
||||||
|
rr.Condition.CreatedBefore = r.Condition.CreatedBefore.Format(rfc3339Date)
|
||||||
|
}
|
||||||
|
rl.Rule = append(rl.Rule, rr)
|
||||||
|
}
|
||||||
|
return &rl
|
||||||
|
}
|
||||||
|
|
||||||
|
func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
|
||||||
|
var l Lifecycle
|
||||||
|
if rl == nil {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
for _, rr := range rl.Rule {
|
||||||
|
r := LifecycleRule{
|
||||||
|
Action: LifecycleAction{
|
||||||
|
Type: rr.Action.Type,
|
||||||
|
StorageClass: rr.Action.StorageClass,
|
||||||
|
},
|
||||||
|
Condition: LifecycleCondition{
|
||||||
|
AgeInDays: rr.Condition.Age,
|
||||||
|
MatchesStorageClasses: rr.Condition.MatchesStorageClass,
|
||||||
|
NumNewerVersions: rr.Condition.NumNewerVersions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case rr.Condition.IsLive == nil:
|
||||||
|
r.Condition.Liveness = LiveAndArchived
|
||||||
|
case *rr.Condition.IsLive == true:
|
||||||
|
r.Condition.Liveness = Live
|
||||||
|
case *rr.Condition.IsLive == false:
|
||||||
|
r.Condition.Liveness = Archived
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.Condition.CreatedBefore != "" {
|
||||||
|
r.Condition.CreatedBefore, _ = time.Parse(rfc3339Date, rr.Condition.CreatedBefore)
|
||||||
|
}
|
||||||
|
l.Rules = append(l.Rules, r)
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// Objects returns an iterator over the objects in the bucket that match the Query q.
|
// Objects returns an iterator over the objects in the bucket that match the Query q.
|
||||||
// If q is nil, no filtering is done.
|
// If q is nil, no filtering is done.
|
||||||
func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
|
func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
|
||||||
|
@ -231,11 +662,15 @@ func (it *ObjectIterator) Next() (*ObjectAttrs, error) {
|
||||||
|
|
||||||
func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error) {
|
func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error) {
|
||||||
req := it.bucket.c.raw.Objects.List(it.bucket.name)
|
req := it.bucket.c.raw.Objects.List(it.bucket.name)
|
||||||
|
setClientHeader(req.Header())
|
||||||
req.Projection("full")
|
req.Projection("full")
|
||||||
req.Delimiter(it.query.Delimiter)
|
req.Delimiter(it.query.Delimiter)
|
||||||
req.Prefix(it.query.Prefix)
|
req.Prefix(it.query.Prefix)
|
||||||
req.Versions(it.query.Versions)
|
req.Versions(it.query.Versions)
|
||||||
req.PageToken(pageToken)
|
req.PageToken(pageToken)
|
||||||
|
if it.bucket.userProject != "" {
|
||||||
|
req.UserProject(it.bucket.userProject)
|
||||||
|
}
|
||||||
if pageSize > 0 {
|
if pageSize > 0 {
|
||||||
req.MaxResults(int64(pageSize))
|
req.MaxResults(int64(pageSize))
|
||||||
}
|
}
|
||||||
|
@ -309,6 +744,7 @@ func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
|
||||||
|
|
||||||
func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error) {
|
func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error) {
|
||||||
req := it.client.raw.Buckets.List(it.projectID)
|
req := it.client.raw.Buckets.List(it.projectID)
|
||||||
|
setClientHeader(req.Header())
|
||||||
req.Projection("full")
|
req.Projection("full")
|
||||||
req.Prefix(it.Prefix)
|
req.Prefix(it.Prefix)
|
||||||
req.PageToken(pageToken)
|
req.PageToken(pageToken)
|
||||||
|
|
|
@ -12,15 +12,11 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package storage contains a Google Cloud Storage client.
|
|
||||||
//
|
|
||||||
// This package is experimental and may make backwards-incompatible changes.
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
@ -29,6 +25,9 @@ import (
|
||||||
// CopierFrom creates a Copier that can copy src to dst.
|
// CopierFrom creates a Copier that can copy src to dst.
|
||||||
// You can immediately call Run on the returned Copier, or
|
// You can immediately call Run on the returned Copier, or
|
||||||
// you can configure it first.
|
// you can configure it first.
|
||||||
|
//
|
||||||
|
// For Requester Pays buckets, the user project of dst is billed, unless it is empty,
|
||||||
|
// in which case the user project of src is billed.
|
||||||
func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier {
|
func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier {
|
||||||
return &Copier{dst: dst, src: src}
|
return &Copier{dst: dst, src: src}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +45,7 @@ type Copier struct {
|
||||||
RewriteToken string
|
RewriteToken string
|
||||||
|
|
||||||
// ProgressFunc can be used to monitor the progress of a multi-RPC copy
|
// ProgressFunc can be used to monitor the progress of a multi-RPC copy
|
||||||
// operation. If ProgressFunc is not nil and CopyFrom requires multiple
|
// operation. If ProgressFunc is not nil and copying requires multiple
|
||||||
// calls to the underlying service (see
|
// calls to the underlying service (see
|
||||||
// https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite), then
|
// https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite), then
|
||||||
// ProgressFunc will be invoked after each call with the number of bytes of
|
// ProgressFunc will be invoked after each call with the number of bytes of
|
||||||
|
@ -71,34 +70,27 @@ func (c *Copier) Run(ctx context.Context) (*ObjectAttrs, error) {
|
||||||
if err := c.dst.validate(); err != nil {
|
if err := c.dst.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var rawObject *raw.Object
|
// Convert destination attributes to raw form, omitting the bucket.
|
||||||
// If any attribute was set, then we make sure the name matches the destination
|
// If the bucket is included but name or content-type aren't, the service
|
||||||
// name, and we check that ContentType is non-empty so we can provide a better
|
// returns a 400 with "Required" as the only message. Omitting the bucket
|
||||||
// error message than the service.
|
// does not cause any problems.
|
||||||
if !reflect.DeepEqual(c.ObjectAttrs, ObjectAttrs{}) {
|
rawObject := c.ObjectAttrs.toRawObject("")
|
||||||
c.ObjectAttrs.Name = c.dst.object
|
|
||||||
if c.ObjectAttrs.ContentType == "" {
|
|
||||||
return nil, errors.New("storage: Copier.ContentType must be non-empty")
|
|
||||||
}
|
|
||||||
rawObject = c.ObjectAttrs.toRawObject(c.dst.bucket)
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
res, err := c.callRewrite(ctx, c.src, rawObject)
|
res, err := c.callRewrite(ctx, rawObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if c.ProgressFunc != nil {
|
if c.ProgressFunc != nil {
|
||||||
c.ProgressFunc(res.TotalBytesRewritten, res.ObjectSize)
|
c.ProgressFunc(uint64(res.TotalBytesRewritten), uint64(res.ObjectSize))
|
||||||
}
|
}
|
||||||
if res.Done { // Finished successfully.
|
if res.Done { // Finished successfully.
|
||||||
return newObject(res.Resource), nil
|
return newObject(res.Resource), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Copier) callRewrite(ctx context.Context, src *ObjectHandle, rawObj *raw.Object) (*raw.RewriteResponse, error) {
|
func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.RewriteResponse, error) {
|
||||||
call := c.dst.c.raw.Objects.Rewrite(src.bucket, src.object, c.dst.bucket, c.dst.object, rawObj)
|
call := c.dst.c.raw.Objects.Rewrite(c.src.bucket, c.src.object, c.dst.bucket, c.dst.object, rawObj)
|
||||||
|
|
||||||
call.Context(ctx).Projection("full")
|
call.Context(ctx).Projection("full")
|
||||||
if c.RewriteToken != "" {
|
if c.RewriteToken != "" {
|
||||||
|
@ -107,6 +99,11 @@ func (c *Copier) callRewrite(ctx context.Context, src *ObjectHandle, rawObj *raw
|
||||||
if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
|
if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if c.dst.userProject != "" {
|
||||||
|
call.UserProject(c.dst.userProject)
|
||||||
|
} else if c.src.userProject != "" {
|
||||||
|
call.UserProject(c.src.userProject)
|
||||||
|
}
|
||||||
if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil {
|
if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -118,6 +115,7 @@ func (c *Copier) callRewrite(ctx context.Context, src *ObjectHandle, rawObj *raw
|
||||||
}
|
}
|
||||||
var res *raw.RewriteResponse
|
var res *raw.RewriteResponse
|
||||||
var err error
|
var err error
|
||||||
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { res, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { res, err = call.Do(); return err })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -138,6 +136,8 @@ func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Composer composes source objects into a destination object.
|
// A Composer composes source objects into a destination object.
|
||||||
|
//
|
||||||
|
// For Requester Pays buckets, the user project of dst is billed.
|
||||||
type Composer struct {
|
type Composer struct {
|
||||||
// ObjectAttrs are optional attributes to set on the destination object.
|
// ObjectAttrs are optional attributes to set on the destination object.
|
||||||
// Any attributes must be initialized before any calls on the Composer. Nil
|
// Any attributes must be initialized before any calls on the Composer. Nil
|
||||||
|
@ -184,11 +184,15 @@ func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) {
|
||||||
if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil {
|
if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if c.dst.userProject != "" {
|
||||||
|
call.UserProject(c.dst.userProject)
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
var err error
|
||||||
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -36,6 +36,13 @@ To start working with this package, create a client:
|
||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The client will use your default application credentials.
|
||||||
|
|
||||||
|
If you only wish to access public data, you can create
|
||||||
|
an unauthenticated client with
|
||||||
|
|
||||||
|
client, err := storage.NewClient(ctx, option.WithoutAuthentication())
|
||||||
|
|
||||||
Buckets
|
Buckets
|
||||||
|
|
||||||
A Google Cloud Storage bucket is a collection of objects. To work with a
|
A Google Cloud Storage bucket is a collection of objects. To work with a
|
||||||
|
@ -152,5 +159,10 @@ SignedURL for details.
|
||||||
// TODO: Handle error.
|
// TODO: Handle error.
|
||||||
}
|
}
|
||||||
fmt.Println(url)
|
fmt.Println(url)
|
||||||
|
|
||||||
|
Authentication
|
||||||
|
|
||||||
|
See examples of authorization and authentication at
|
||||||
|
https://godoc.org/cloud.google.com/go#pkg-examples.
|
||||||
*/
|
*/
|
||||||
package storage // import "cloud.google.com/go/storage"
|
package storage // import "cloud.google.com/go/storage"
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.10
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import "google.golang.org/api/googleapi"
|
||||||
|
|
||||||
|
func shouldRetry(err error) bool {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *googleapi.Error:
|
||||||
|
// Retry on 429 and 5xx, according to
|
||||||
|
// https://cloud.google.com/storage/docs/exponential-backoff.
|
||||||
|
return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withContext(r *http.Request, ctx context.Context) *http.Request {
|
||||||
|
return r.WithContext(ctx)
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cloud.google.com/go/iam"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
iampb "google.golang.org/genproto/googleapis/iam/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IAM provides access to IAM access control for the bucket.
|
||||||
|
func (b *BucketHandle) IAM() *iam.Handle {
|
||||||
|
return iam.InternalNewHandleClient(&iamClient{
|
||||||
|
raw: b.c.raw,
|
||||||
|
userProject: b.userProject,
|
||||||
|
}, b.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// iamClient implements the iam.client interface.
|
||||||
|
type iamClient struct {
|
||||||
|
raw *raw.Service
|
||||||
|
userProject string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Get(ctx context.Context, resource string) (*iampb.Policy, error) {
|
||||||
|
call := c.raw.Buckets.GetIamPolicy(resource)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
var rp *raw.Policy
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
rp, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iamFromStoragePolicy(rp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) error {
|
||||||
|
rp := iamToStoragePolicy(p)
|
||||||
|
call := c.raw.Buckets.SetIamPolicy(resource, rp)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
_, err := call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
|
||||||
|
call := c.raw.Buckets.TestIamPermissions(resource, perms)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
var res *raw.TestIamPermissionsResponse
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Permissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamToStoragePolicy(ip *iampb.Policy) *raw.Policy {
|
||||||
|
return &raw.Policy{
|
||||||
|
Bindings: iamToStorageBindings(ip.Bindings),
|
||||||
|
Etag: string(ip.Etag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamToStorageBindings(ibs []*iampb.Binding) []*raw.PolicyBindings {
|
||||||
|
var rbs []*raw.PolicyBindings
|
||||||
|
for _, ib := range ibs {
|
||||||
|
rbs = append(rbs, &raw.PolicyBindings{
|
||||||
|
Role: ib.Role,
|
||||||
|
Members: ib.Members,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return rbs
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamFromStoragePolicy(rp *raw.Policy) *iampb.Policy {
|
||||||
|
return &iampb.Policy{
|
||||||
|
Bindings: iamFromStorageBindings(rp.Bindings),
|
||||||
|
Etag: []byte(rp.Etag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamFromStorageBindings(rbs []*raw.PolicyBindings) []*iampb.Binding {
|
||||||
|
var ibs []*iampb.Binding
|
||||||
|
for _, rb := range rbs {
|
||||||
|
ibs = append(ibs, &iampb.Binding{
|
||||||
|
Role: rb.Role,
|
||||||
|
Members: rb.Members,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ibs
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"cloud.google.com/go/internal"
|
"cloud.google.com/go/internal"
|
||||||
gax "github.com/googleapis/gax-go"
|
gax "github.com/googleapis/gax-go"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/googleapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// runWithRetry calls the function until it returns nil or a non-retryable error, or
|
// runWithRetry calls the function until it returns nil or a non-retryable error, or
|
||||||
|
@ -29,13 +28,7 @@ func runWithRetry(ctx context.Context, call func() error) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
e, ok := err.(*googleapi.Error)
|
if shouldRetry(err) {
|
||||||
if !ok {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
// Retry on 429 and 5xx, according to
|
|
||||||
// https://cloud.google.com/storage/docs/exponential-backoff.
|
|
||||||
if e.Code == 429 || (e.Code >= 500 && e.Code < 600) {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return true, err
|
return true, err
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.10
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func shouldRetry(err error) bool {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *googleapi.Error:
|
||||||
|
// Retry on 429 and 5xx, according to
|
||||||
|
// https://cloud.google.com/storage/docs/exponential-backoff.
|
||||||
|
return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
|
||||||
|
case *url.Error:
|
||||||
|
// Retry on REFUSED_STREAM.
|
||||||
|
// Unfortunately the error type is unexported, so we resort to string
|
||||||
|
// matching.
|
||||||
|
return strings.Contains(e.Error(), "REFUSED_STREAM")
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withContext(r *http.Request, _ interface{}) *http.Request {
|
||||||
|
// In Go 1.6 and below, ignore the context.
|
||||||
|
return r
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Notification describes how to send Cloud PubSub messages when certain
|
||||||
|
// events occur in a bucket.
|
||||||
|
type Notification struct {
|
||||||
|
//The ID of the notification.
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// The ID of the topic to which this subscription publishes.
|
||||||
|
TopicID string
|
||||||
|
|
||||||
|
// The ID of the project to which the topic belongs.
|
||||||
|
TopicProjectID string
|
||||||
|
|
||||||
|
// Only send notifications about listed event types. If empty, send notifications
|
||||||
|
// for all event types.
|
||||||
|
// See https://cloud.google.com/storage/docs/pubsub-notifications#events.
|
||||||
|
EventTypes []string
|
||||||
|
|
||||||
|
// If present, only apply this notification configuration to object names that
|
||||||
|
// begin with this prefix.
|
||||||
|
ObjectNamePrefix string
|
||||||
|
|
||||||
|
// An optional list of additional attributes to attach to each Cloud PubSub
|
||||||
|
// message published for this notification subscription.
|
||||||
|
CustomAttributes map[string]string
|
||||||
|
|
||||||
|
// The contents of the message payload.
|
||||||
|
// See https://cloud.google.com/storage/docs/pubsub-notifications#payload.
|
||||||
|
PayloadFormat string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values for Notification.PayloadFormat.
|
||||||
|
const (
|
||||||
|
// Send no payload with notification messages.
|
||||||
|
NoPayload = "NONE"
|
||||||
|
|
||||||
|
// Send object metadata as JSON with notification messages.
|
||||||
|
JSONPayload = "JSON_API_V1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Values for Notification.EventTypes.
|
||||||
|
const (
|
||||||
|
// Event that occurs when an object is successfully created.
|
||||||
|
ObjectFinalizeEvent = "OBJECT_FINALIZE"
|
||||||
|
|
||||||
|
// Event that occurs when the metadata of an existing object changes.
|
||||||
|
ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
|
||||||
|
|
||||||
|
// Event that occurs when an object is permanently deleted.
|
||||||
|
ObjectDeleteEvent = "OBJECT_DELETE"
|
||||||
|
|
||||||
|
// Event that occurs when the live version of an object becomes an
|
||||||
|
// archived version.
|
||||||
|
ObjectArchiveEvent = "OBJECT_ARCHIVE"
|
||||||
|
)
|
||||||
|
|
||||||
|
func toNotification(rn *raw.Notification) *Notification {
|
||||||
|
n := &Notification{
|
||||||
|
ID: rn.Id,
|
||||||
|
EventTypes: rn.EventTypes,
|
||||||
|
ObjectNamePrefix: rn.ObjectNamePrefix,
|
||||||
|
CustomAttributes: rn.CustomAttributes,
|
||||||
|
PayloadFormat: rn.PayloadFormat,
|
||||||
|
}
|
||||||
|
n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
|
||||||
|
|
||||||
|
// parseNotificationTopic extracts the project and topic IDs from from the full
|
||||||
|
// resource name returned by the service. If the name is malformed, it returns
|
||||||
|
// "?" for both IDs.
|
||||||
|
func parseNotificationTopic(nt string) (projectID, topicID string) {
|
||||||
|
matches := topicRE.FindStringSubmatch(nt)
|
||||||
|
if matches == nil {
|
||||||
|
return "?", "?"
|
||||||
|
}
|
||||||
|
return matches[1], matches[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawNotification(n *Notification) *raw.Notification {
|
||||||
|
return &raw.Notification{
|
||||||
|
Id: n.ID,
|
||||||
|
Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
|
||||||
|
n.TopicProjectID, n.TopicID),
|
||||||
|
EventTypes: n.EventTypes,
|
||||||
|
ObjectNamePrefix: n.ObjectNamePrefix,
|
||||||
|
CustomAttributes: n.CustomAttributes,
|
||||||
|
PayloadFormat: string(n.PayloadFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
|
||||||
|
// and PayloadFormat, and must not set its ID. The other fields are all optional. The
|
||||||
|
// returned Notification's ID can be used to refer to it.
|
||||||
|
func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (*Notification, error) {
|
||||||
|
if n.ID != "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: ID must not be set")
|
||||||
|
}
|
||||||
|
if n.TopicProjectID == "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: missing TopicProjectID")
|
||||||
|
}
|
||||||
|
if n.TopicID == "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: missing TopicID")
|
||||||
|
}
|
||||||
|
call := b.c.raw.Notifications.Insert(b.name, toRawNotification(n))
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
rn, err := call.Context(ctx).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toNotification(rn), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifications returns all the Notifications configured for this bucket, as a map
|
||||||
|
// indexed by notification ID.
|
||||||
|
func (b *BucketHandle) Notifications(ctx context.Context) (map[string]*Notification, error) {
|
||||||
|
call := b.c.raw.Notifications.List(b.name)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
var res *raw.Notifications
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return notificationsToMap(res.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
|
||||||
|
m := map[string]*Notification{}
|
||||||
|
for _, rn := range rns {
|
||||||
|
m[rn.Id] = toNotification(rn)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNotification deletes the notification with the given ID.
|
||||||
|
func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) error {
|
||||||
|
call := b.c.raw.Notifications.Delete(b.name, id)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
return call.Context(ctx).Do()
|
||||||
|
}
|
|
@ -15,15 +15,24 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
||||||
|
|
||||||
// Reader reads a Cloud Storage object.
|
// Reader reads a Cloud Storage object.
|
||||||
// It implements io.Reader.
|
// It implements io.Reader.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
body io.ReadCloser
|
body io.ReadCloser
|
||||||
remain, size int64
|
remain, size int64
|
||||||
contentType string
|
contentType string
|
||||||
|
contentEncoding string
|
||||||
|
cacheControl string
|
||||||
|
checkCRC bool // should we check the CRC?
|
||||||
|
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||||
|
gotCRC uint32 // running crc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the Reader. It must be called when done reading.
|
// Close closes the Reader. It must be called when done reading.
|
||||||
|
@ -36,6 +45,16 @@ func (r *Reader) Read(p []byte) (int, error) {
|
||||||
if r.remain != -1 {
|
if r.remain != -1 {
|
||||||
r.remain -= int64(n)
|
r.remain -= int64(n)
|
||||||
}
|
}
|
||||||
|
if r.checkCRC {
|
||||||
|
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[:n])
|
||||||
|
// Check CRC here. It would be natural to check it in Close, but
|
||||||
|
// everybody defers Close on the assumption that it doesn't return
|
||||||
|
// anything worth looking at.
|
||||||
|
if r.remain == 0 && r.gotCRC != r.wantCRC {
|
||||||
|
return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
|
||||||
|
r.gotCRC, r.wantCRC)
|
||||||
|
}
|
||||||
|
}
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,3 +74,13 @@ func (r *Reader) Remain() int64 {
|
||||||
func (r *Reader) ContentType() string {
|
func (r *Reader) ContentType() string {
|
||||||
return r.contentType
|
return r.contentType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContentEncoding returns the content encoding of the object.
|
||||||
|
func (r *Reader) ContentEncoding() string {
|
||||||
|
return r.contentEncoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheControl returns the cache control of the object.
|
||||||
|
func (r *Reader) CacheControl() string {
|
||||||
|
return r.cacheControl
|
||||||
|
}
|
||||||
|
|
|
@ -36,9 +36,10 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
"google.golang.org/api/transport"
|
htransport "google.golang.org/api/transport/http"
|
||||||
|
|
||||||
"cloud.google.com/go/internal/optional"
|
"cloud.google.com/go/internal/optional"
|
||||||
|
"cloud.google.com/go/internal/version"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
raw "google.golang.org/api/storage/v1"
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
@ -65,6 +66,12 @@ const (
|
||||||
ScopeReadWrite = raw.DevstorageReadWriteScope
|
ScopeReadWrite = raw.DevstorageReadWriteScope
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var xGoogHeader = fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo)
|
||||||
|
|
||||||
|
func setClientHeader(headers http.Header) {
|
||||||
|
headers.Set("x-goog-api-client", xGoogHeader)
|
||||||
|
}
|
||||||
|
|
||||||
// Client is a client for interacting with Google Cloud Storage.
|
// Client is a client for interacting with Google Cloud Storage.
|
||||||
//
|
//
|
||||||
// Clients should be reused instead of created as needed.
|
// Clients should be reused instead of created as needed.
|
||||||
|
@ -82,7 +89,7 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error
|
||||||
option.WithUserAgent(userAgent),
|
option.WithUserAgent(userAgent),
|
||||||
}
|
}
|
||||||
opts = append(o, opts...)
|
opts = append(o, opts...)
|
||||||
hc, _, err := transport.NewHTTPClient(ctx, opts...)
|
hc, ep, err := htransport.NewClient(ctx, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("dialing: %v", err)
|
return nil, fmt.Errorf("dialing: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -90,6 +97,9 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("storage client: %v", err)
|
return nil, fmt.Errorf("storage client: %v", err)
|
||||||
}
|
}
|
||||||
|
if ep != "" {
|
||||||
|
rawService.BasePath = ep
|
||||||
|
}
|
||||||
return &Client{
|
return &Client{
|
||||||
hc: hc,
|
hc: hc,
|
||||||
raw: rawService,
|
raw: rawService,
|
||||||
|
@ -100,43 +110,13 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error
|
||||||
//
|
//
|
||||||
// Close need not be called at program exit.
|
// Close need not be called at program exit.
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
|
// Set fields to nil so that subsequent uses
|
||||||
|
// will panic.
|
||||||
c.hc = nil
|
c.hc = nil
|
||||||
|
c.raw = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BucketHandle provides operations on a Google Cloud Storage bucket.
|
|
||||||
// Use Client.Bucket to get a handle.
|
|
||||||
type BucketHandle struct {
|
|
||||||
acl ACLHandle
|
|
||||||
defaultObjectACL ACLHandle
|
|
||||||
|
|
||||||
c *Client
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucket returns a BucketHandle, which provides operations on the named bucket.
|
|
||||||
// This call does not perform any network operations.
|
|
||||||
//
|
|
||||||
// The supplied name must contain only lowercase letters, numbers, dashes,
|
|
||||||
// underscores, and dots. The full specification for valid bucket names can be
|
|
||||||
// found at:
|
|
||||||
// https://cloud.google.com/storage/docs/bucket-naming
|
|
||||||
func (c *Client) Bucket(name string) *BucketHandle {
|
|
||||||
return &BucketHandle{
|
|
||||||
c: c,
|
|
||||||
name: name,
|
|
||||||
acl: ACLHandle{
|
|
||||||
c: c,
|
|
||||||
bucket: name,
|
|
||||||
},
|
|
||||||
defaultObjectACL: ACLHandle{
|
|
||||||
c: c,
|
|
||||||
bucket: name,
|
|
||||||
isDefault: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignedURLOptions allows you to restrict the access to the signed URL.
|
// SignedURLOptions allows you to restrict the access to the signed URL.
|
||||||
type SignedURLOptions struct {
|
type SignedURLOptions struct {
|
||||||
// GoogleAccessID represents the authorizer of the signed URL generation.
|
// GoogleAccessID represents the authorizer of the signed URL generation.
|
||||||
|
@ -190,7 +170,7 @@ type SignedURLOptions struct {
|
||||||
// Optional.
|
// Optional.
|
||||||
ContentType string
|
ContentType string
|
||||||
|
|
||||||
// Headers is a list of extention headers the client must provide
|
// Headers is a list of extension headers the client must provide
|
||||||
// in order to use the generated signed URL.
|
// in order to use the generated signed URL.
|
||||||
// Optional.
|
// Optional.
|
||||||
Headers []string
|
Headers []string
|
||||||
|
@ -199,7 +179,7 @@ type SignedURLOptions struct {
|
||||||
// If provided, the client should provide the exact value on the request
|
// If provided, the client should provide the exact value on the request
|
||||||
// header in order to use the signed URL.
|
// header in order to use the signed URL.
|
||||||
// Optional.
|
// Optional.
|
||||||
MD5 []byte
|
MD5 string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignedURL returns a URL for the specified object. Signed URLs allow
|
// SignedURL returns a URL for the specified object. Signed URLs allow
|
||||||
|
@ -222,6 +202,12 @@ func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
|
||||||
if opts.Expires.IsZero() {
|
if opts.Expires.IsZero() {
|
||||||
return "", errors.New("storage: missing required expires option")
|
return "", errors.New("storage: missing required expires option")
|
||||||
}
|
}
|
||||||
|
if opts.MD5 != "" {
|
||||||
|
md5, err := base64.StdEncoding.DecodeString(opts.MD5)
|
||||||
|
if err != nil || len(md5) != 16 {
|
||||||
|
return "", errors.New("storage: invalid MD5 checksum")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
signBytes := opts.SignBytes
|
signBytes := opts.SignBytes
|
||||||
if opts.PrivateKey != nil {
|
if opts.PrivateKey != nil {
|
||||||
|
@ -238,8 +224,6 @@ func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
|
||||||
sum[:],
|
sum[:],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
signBytes = opts.SignBytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u := &url.URL{
|
u := &url.URL{
|
||||||
|
@ -251,7 +235,9 @@ func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
|
||||||
fmt.Fprintf(buf, "%s\n", opts.MD5)
|
fmt.Fprintf(buf, "%s\n", opts.MD5)
|
||||||
fmt.Fprintf(buf, "%s\n", opts.ContentType)
|
fmt.Fprintf(buf, "%s\n", opts.ContentType)
|
||||||
fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
|
fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
|
||||||
fmt.Fprintf(buf, "%s", strings.Join(opts.Headers, "\n"))
|
if len(opts.Headers) > 0 {
|
||||||
|
fmt.Fprintf(buf, "%s\n", strings.Join(opts.Headers, "\n"))
|
||||||
|
}
|
||||||
fmt.Fprintf(buf, "%s", u.String())
|
fmt.Fprintf(buf, "%s", u.String())
|
||||||
|
|
||||||
b, err := signBytes(buf.Bytes())
|
b, err := signBytes(buf.Bytes())
|
||||||
|
@ -279,6 +265,8 @@ type ObjectHandle struct {
|
||||||
gen int64 // a negative value indicates latest
|
gen int64 // a negative value indicates latest
|
||||||
conds *Conditions
|
conds *Conditions
|
||||||
encryptionKey []byte // AES-256 key
|
encryptionKey []byte // AES-256 key
|
||||||
|
userProject string // for requester-pays buckets
|
||||||
|
readCompressed bool // Accept-Encoding: gzip
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACL provides access to the object's access control list.
|
// ACL provides access to the object's access control list.
|
||||||
|
@ -331,11 +319,15 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
|
||||||
if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
|
if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if o.userProject != "" {
|
||||||
|
call.UserProject(o.userProject)
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
var err error
|
||||||
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||||
return nil, ErrObjectNotExist
|
return nil, ErrObjectNotExist
|
||||||
|
@ -358,11 +350,17 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
|
||||||
var forceSendFields, nullFields []string
|
var forceSendFields, nullFields []string
|
||||||
if uattrs.ContentType != nil {
|
if uattrs.ContentType != nil {
|
||||||
attrs.ContentType = optional.ToString(uattrs.ContentType)
|
attrs.ContentType = optional.ToString(uattrs.ContentType)
|
||||||
|
// For ContentType, sending the empty string is a no-op.
|
||||||
|
// Instead we send a null.
|
||||||
|
if attrs.ContentType == "" {
|
||||||
|
nullFields = append(nullFields, "ContentType")
|
||||||
|
} else {
|
||||||
forceSendFields = append(forceSendFields, "ContentType")
|
forceSendFields = append(forceSendFields, "ContentType")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if uattrs.ContentLanguage != nil {
|
if uattrs.ContentLanguage != nil {
|
||||||
attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
|
attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
|
||||||
// For ContentLanguage It's an error to send the empty string.
|
// For ContentLanguage it's an error to send the empty string.
|
||||||
// Instead we send a null.
|
// Instead we send a null.
|
||||||
if attrs.ContentLanguage == "" {
|
if attrs.ContentLanguage == "" {
|
||||||
nullFields = append(nullFields, "ContentLanguage")
|
nullFields = append(nullFields, "ContentLanguage")
|
||||||
|
@ -372,7 +370,7 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
|
||||||
}
|
}
|
||||||
if uattrs.ContentEncoding != nil {
|
if uattrs.ContentEncoding != nil {
|
||||||
attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
|
attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
|
||||||
forceSendFields = append(forceSendFields, "ContentType")
|
forceSendFields = append(forceSendFields, "ContentEncoding")
|
||||||
}
|
}
|
||||||
if uattrs.ContentDisposition != nil {
|
if uattrs.ContentDisposition != nil {
|
||||||
attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
|
attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
|
||||||
|
@ -404,11 +402,15 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
|
||||||
if err := applyConds("Update", o.gen, o.conds, call); err != nil {
|
if err := applyConds("Update", o.gen, o.conds, call); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if o.userProject != "" {
|
||||||
|
call.UserProject(o.userProject)
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var obj *raw.Object
|
var obj *raw.Object
|
||||||
var err error
|
var err error
|
||||||
|
setClientHeader(call.Header())
|
||||||
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
|
||||||
return nil, ErrObjectNotExist
|
return nil, ErrObjectNotExist
|
||||||
|
@ -449,6 +451,11 @@ func (o *ObjectHandle) Delete(ctx context.Context) error {
|
||||||
if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
|
if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if o.userProject != "" {
|
||||||
|
call.UserProject(o.userProject)
|
||||||
|
}
|
||||||
|
// Encryption doesn't apply to Delete.
|
||||||
|
setClientHeader(call.Header())
|
||||||
err := runWithRetry(ctx, func() error { return call.Do() })
|
err := runWithRetry(ctx, func() error { return call.Do() })
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
|
@ -461,6 +468,13 @@ func (o *ObjectHandle) Delete(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadCompressed when true causes the read to happen without decompressing.
|
||||||
|
func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
|
||||||
|
o2 := *o
|
||||||
|
o2.readCompressed = compressed
|
||||||
|
return &o2
|
||||||
|
}
|
||||||
|
|
||||||
// NewReader creates a new Reader to read the contents of the
|
// NewReader creates a new Reader to read the contents of the
|
||||||
// object.
|
// object.
|
||||||
// ErrObjectNotExist will be returned if the object is not found.
|
// ErrObjectNotExist will be returned if the object is not found.
|
||||||
|
@ -499,27 +513,35 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
req = withContext(req, ctx)
|
||||||
if length < 0 && offset > 0 {
|
if length < 0 && offset > 0 {
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
||||||
} else if length > 0 {
|
} else if length > 0 {
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
|
||||||
}
|
}
|
||||||
|
if o.userProject != "" {
|
||||||
|
req.Header.Set("X-Goog-User-Project", o.userProject)
|
||||||
|
}
|
||||||
|
if o.readCompressed {
|
||||||
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var res *http.Response
|
var res *http.Response
|
||||||
err = runWithRetry(ctx, func() error { res, err = o.c.hc.Do(req); return err })
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = o.c.hc.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if res.StatusCode == http.StatusNotFound {
|
if res.StatusCode == http.StatusNotFound {
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
return nil, ErrObjectNotExist
|
return ErrObjectNotExist
|
||||||
}
|
}
|
||||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||||
body, _ := ioutil.ReadAll(res.Body)
|
body, _ := ioutil.ReadAll(res.Body)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
return nil, &googleapi.Error{
|
return &googleapi.Error{
|
||||||
Code: res.StatusCode,
|
Code: res.StatusCode,
|
||||||
Header: res.Header,
|
Header: res.Header,
|
||||||
Body: string(body),
|
Body: string(body),
|
||||||
|
@ -527,7 +549,12 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||||
}
|
}
|
||||||
if offset > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
|
if offset > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
return nil, errors.New("storage: partial request not satisfied")
|
return errors.New("storage: partial request not satisfied")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var size int64 // total size of object, even if a range was requested.
|
var size int64 // total size of object, even if a range was requested.
|
||||||
|
@ -551,15 +578,39 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
|
||||||
body.Close()
|
body.Close()
|
||||||
body = emptyBody
|
body = emptyBody
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
checkCRC bool
|
||||||
|
crc uint32
|
||||||
|
)
|
||||||
|
// Even if there is a CRC header, we can't compute the hash on partial data.
|
||||||
|
if remain == size {
|
||||||
|
crc, checkCRC = parseCRC32c(res)
|
||||||
|
}
|
||||||
return &Reader{
|
return &Reader{
|
||||||
body: body,
|
body: body,
|
||||||
size: size,
|
size: size,
|
||||||
remain: remain,
|
remain: remain,
|
||||||
contentType: res.Header.Get("Content-Type"),
|
contentType: res.Header.Get("Content-Type"),
|
||||||
|
contentEncoding: res.Header.Get("Content-Encoding"),
|
||||||
|
cacheControl: res.Header.Get("Cache-Control"),
|
||||||
|
wantCRC: crc,
|
||||||
|
checkCRC: checkCRC,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseCRC32c(res *http.Response) (uint32, bool) {
|
||||||
|
const prefix = "crc32c="
|
||||||
|
for _, spec := range res.Header["X-Goog-Hash"] {
|
||||||
|
if strings.HasPrefix(spec, prefix) {
|
||||||
|
c, err := decodeUint32(spec[len(prefix):])
|
||||||
|
if err == nil {
|
||||||
|
return c, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
var emptyBody = ioutil.NopCloser(strings.NewReader(""))
|
var emptyBody = ioutil.NopCloser(strings.NewReader(""))
|
||||||
|
|
||||||
// NewWriter returns a storage Writer that writes to the GCS object
|
// NewWriter returns a storage Writer that writes to the GCS object
|
||||||
|
@ -599,11 +650,10 @@ func (o *ObjectHandle) validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseKey converts the binary contents of a private key file
|
// parseKey converts the binary contents of a private key file to an
|
||||||
// to an *rsa.PrivateKey. It detects whether the private key is in a
|
// *rsa.PrivateKey. It detects whether the private key is in a PEM container or
|
||||||
// PEM container or not. If so, it extracts the the private key
|
// not. If so, it extracts the private key from PEM container before
|
||||||
// from PEM container before conversion. It only supports PEM
|
// conversion. It only supports PEM containers with no passphrase.
|
||||||
// containers with no passphrase.
|
|
||||||
func parseKey(key []byte) (*rsa.PrivateKey, error) {
|
func parseKey(key []byte) (*rsa.PrivateKey, error) {
|
||||||
if block, _ := pem.Decode(key); block != nil {
|
if block, _ := pem.Decode(key); block != nil {
|
||||||
key = block.Bytes
|
key = block.Bytes
|
||||||
|
@ -647,6 +697,7 @@ func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
|
||||||
ContentLanguage: o.ContentLanguage,
|
ContentLanguage: o.ContentLanguage,
|
||||||
CacheControl: o.CacheControl,
|
CacheControl: o.CacheControl,
|
||||||
ContentDisposition: o.ContentDisposition,
|
ContentDisposition: o.ContentDisposition,
|
||||||
|
StorageClass: o.StorageClass,
|
||||||
Acl: acl,
|
Acl: acl,
|
||||||
Metadata: o.Metadata,
|
Metadata: o.Metadata,
|
||||||
}
|
}
|
||||||
|
@ -690,11 +741,16 @@ type ObjectAttrs struct {
|
||||||
// sent in the response headers.
|
// sent in the response headers.
|
||||||
ContentDisposition string
|
ContentDisposition string
|
||||||
|
|
||||||
// MD5 is the MD5 hash of the object's content. This field is read-only.
|
// MD5 is the MD5 hash of the object's content. This field is read-only,
|
||||||
|
// except when used from a Writer. If set on a Writer, the uploaded
|
||||||
|
// data is rejected if its MD5 hash does not match this field.
|
||||||
MD5 []byte
|
MD5 []byte
|
||||||
|
|
||||||
// CRC32C is the CRC32 checksum of the object's content using
|
// CRC32C is the CRC32 checksum of the object's content using
|
||||||
// the Castagnoli93 polynomial. This field is read-only.
|
// the Castagnoli93 polynomial. This field is read-only, except when
|
||||||
|
// used from a Writer. If set on a Writer and Writer.SendCRC32C
|
||||||
|
// is true, the uploaded data is rejected if its CRC32c hash does not
|
||||||
|
// match this field.
|
||||||
CRC32C uint32
|
CRC32C uint32
|
||||||
|
|
||||||
// MediaLink is an URL to the object's content. This field is read-only.
|
// MediaLink is an URL to the object's content. This field is read-only.
|
||||||
|
@ -708,21 +764,20 @@ type ObjectAttrs struct {
|
||||||
// This field is read-only.
|
// This field is read-only.
|
||||||
Generation int64
|
Generation int64
|
||||||
|
|
||||||
// MetaGeneration is the version of the metadata for this
|
// Metageneration is the version of the metadata for this
|
||||||
// object at this generation. This field is used for preconditions
|
// object at this generation. This field is used for preconditions
|
||||||
// and for detecting changes in metadata. A metageneration number
|
// and for detecting changes in metadata. A metageneration number
|
||||||
// is only meaningful in the context of a particular generation
|
// is only meaningful in the context of a particular generation
|
||||||
// of a particular object. This field is read-only.
|
// of a particular object. This field is read-only.
|
||||||
MetaGeneration int64
|
Metageneration int64
|
||||||
|
|
||||||
// StorageClass is the storage class of the bucket.
|
// StorageClass is the storage class of the object.
|
||||||
// This value defines how objects in the bucket are stored and
|
// This value defines how objects in the bucket are stored and
|
||||||
// determines the SLA and the cost of storage. Typical values are
|
// determines the SLA and the cost of storage. Typical values are
|
||||||
// "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
|
// "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
|
||||||
// and "DURABLE_REDUCED_AVAILABILITY".
|
// and "DURABLE_REDUCED_AVAILABILITY".
|
||||||
// It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
|
// It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
|
||||||
// or "REGIONAL" depending on the bucket's location settings. This
|
// or "REGIONAL" depending on the bucket's location settings.
|
||||||
// field is read-only.
|
|
||||||
StorageClass string
|
StorageClass string
|
||||||
|
|
||||||
// Created is the time the object was created. This field is read-only.
|
// Created is the time the object was created. This field is read-only.
|
||||||
|
@ -777,11 +832,7 @@ func newObject(o *raw.Object) *ObjectAttrs {
|
||||||
owner = o.Owner.Entity
|
owner = o.Owner.Entity
|
||||||
}
|
}
|
||||||
md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
|
md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
|
||||||
var crc32c uint32
|
crc32c, _ := decodeUint32(o.Crc32c)
|
||||||
d, err := base64.StdEncoding.DecodeString(o.Crc32c)
|
|
||||||
if err == nil && len(d) == 4 {
|
|
||||||
crc32c = uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3])
|
|
||||||
}
|
|
||||||
var sha256 string
|
var sha256 string
|
||||||
if o.CustomerEncryption != nil {
|
if o.CustomerEncryption != nil {
|
||||||
sha256 = o.CustomerEncryption.KeySha256
|
sha256 = o.CustomerEncryption.KeySha256
|
||||||
|
@ -795,13 +846,14 @@ func newObject(o *raw.Object) *ObjectAttrs {
|
||||||
ACL: acl,
|
ACL: acl,
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
ContentEncoding: o.ContentEncoding,
|
ContentEncoding: o.ContentEncoding,
|
||||||
|
ContentDisposition: o.ContentDisposition,
|
||||||
Size: int64(o.Size),
|
Size: int64(o.Size),
|
||||||
MD5: md5,
|
MD5: md5,
|
||||||
CRC32C: crc32c,
|
CRC32C: crc32c,
|
||||||
MediaLink: o.MediaLink,
|
MediaLink: o.MediaLink,
|
||||||
Metadata: o.Metadata,
|
Metadata: o.Metadata,
|
||||||
Generation: o.Generation,
|
Generation: o.Generation,
|
||||||
MetaGeneration: o.Metageneration,
|
Metageneration: o.Metageneration,
|
||||||
StorageClass: o.StorageClass,
|
StorageClass: o.StorageClass,
|
||||||
CustomerKeySHA256: sha256,
|
CustomerKeySHA256: sha256,
|
||||||
Created: convertTime(o.TimeCreated),
|
Created: convertTime(o.TimeCreated),
|
||||||
|
@ -810,6 +862,24 @@ func newObject(o *raw.Object) *ObjectAttrs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode a uint32 encoded in Base64 in big-endian byte order.
|
||||||
|
func decodeUint32(b64 string) (uint32, error) {
|
||||||
|
d, err := base64.StdEncoding.DecodeString(b64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if len(d) != 4 {
|
||||||
|
return 0, fmt.Errorf("storage: %q does not encode a 32-bit value", d)
|
||||||
|
}
|
||||||
|
return uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode a uint32 as Base64 in big-endian byte order.
|
||||||
|
func encodeUint32(u uint32) string {
|
||||||
|
b := []byte{byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u)}
|
||||||
|
return base64.StdEncoding.EncodeToString(b)
|
||||||
|
}
|
||||||
|
|
||||||
// Query represents a query to filter objects from a bucket.
|
// Query represents a query to filter objects from a bucket.
|
||||||
type Query struct {
|
type Query struct {
|
||||||
// Delimiter returns results in a directory-like fashion.
|
// Delimiter returns results in a directory-like fashion.
|
||||||
|
@ -843,7 +913,7 @@ func (c *contentTyper) ContentType() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditions constrain methods to act on specific generations of
|
// Conditions constrain methods to act on specific generations of
|
||||||
// resources.
|
// objects.
|
||||||
//
|
//
|
||||||
// The zero value is an empty set of constraints. Not all conditions or
|
// The zero value is an empty set of constraints. Not all conditions or
|
||||||
// combinations of conditions are applicable to all methods.
|
// combinations of conditions are applicable to all methods.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -32,6 +33,13 @@ type Writer struct {
|
||||||
// attributes are ignored.
|
// attributes are ignored.
|
||||||
ObjectAttrs
|
ObjectAttrs
|
||||||
|
|
||||||
|
// SendCRC specifies whether to transmit a CRC32C field. It should be set
|
||||||
|
// to true in addition to setting the Writer's CRC32C field, because zero
|
||||||
|
// is a valid CRC and normally a zero would not be transmitted.
|
||||||
|
// If a CRC32C is sent, and the data written does not match the checksum,
|
||||||
|
// the write will be rejected.
|
||||||
|
SendCRC32C bool
|
||||||
|
|
||||||
// ChunkSize controls the maximum number of bytes of the object that the
|
// ChunkSize controls the maximum number of bytes of the object that the
|
||||||
// Writer will attempt to send to the server in a single request. Objects
|
// Writer will attempt to send to the server in a single request. Objects
|
||||||
// smaller than the size will be sent in a single request, while larger
|
// smaller than the size will be sent in a single request, while larger
|
||||||
|
@ -43,6 +51,16 @@ type Writer struct {
|
||||||
// must be done before the first Write call.
|
// must be done before the first Write call.
|
||||||
ChunkSize int
|
ChunkSize int
|
||||||
|
|
||||||
|
// ProgressFunc can be used to monitor the progress of a large write.
|
||||||
|
// operation. If ProgressFunc is not nil and writing requires multiple
|
||||||
|
// calls to the underlying service (see
|
||||||
|
// https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload),
|
||||||
|
// then ProgressFunc will be invoked after each call with the number of bytes of
|
||||||
|
// content copied so far.
|
||||||
|
//
|
||||||
|
// ProgressFunc should return quickly without blocking.
|
||||||
|
ProgressFunc func(int64)
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
o *ObjectHandle
|
o *ObjectHandle
|
||||||
|
|
||||||
|
@ -69,7 +87,7 @@ func (w *Writer) open() error {
|
||||||
w.opened = true
|
w.opened = true
|
||||||
|
|
||||||
if w.ChunkSize < 0 {
|
if w.ChunkSize < 0 {
|
||||||
return errors.New("storage: Writer.ChunkSize must non-negative")
|
return errors.New("storage: Writer.ChunkSize must be non-negative")
|
||||||
}
|
}
|
||||||
mediaOpts := []googleapi.MediaOption{
|
mediaOpts := []googleapi.MediaOption{
|
||||||
googleapi.ChunkSize(w.ChunkSize),
|
googleapi.ChunkSize(w.ChunkSize),
|
||||||
|
@ -81,10 +99,20 @@ func (w *Writer) open() error {
|
||||||
go func() {
|
go func() {
|
||||||
defer close(w.donec)
|
defer close(w.donec)
|
||||||
|
|
||||||
call := w.o.c.raw.Objects.Insert(w.o.bucket, attrs.toRawObject(w.o.bucket)).
|
rawObj := attrs.toRawObject(w.o.bucket)
|
||||||
|
if w.SendCRC32C {
|
||||||
|
rawObj.Crc32c = encodeUint32(attrs.CRC32C)
|
||||||
|
}
|
||||||
|
if w.MD5 != nil {
|
||||||
|
rawObj.Md5Hash = base64.StdEncoding.EncodeToString(w.MD5)
|
||||||
|
}
|
||||||
|
call := w.o.c.raw.Objects.Insert(w.o.bucket, rawObj).
|
||||||
Media(pr, mediaOpts...).
|
Media(pr, mediaOpts...).
|
||||||
Projection("full").
|
Projection("full").
|
||||||
Context(w.ctx)
|
Context(w.ctx)
|
||||||
|
if w.ProgressFunc != nil {
|
||||||
|
call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
|
||||||
|
}
|
||||||
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
|
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
|
||||||
w.err = err
|
w.err = err
|
||||||
pr.CloseWithError(w.err)
|
pr.CloseWithError(w.err)
|
||||||
|
@ -93,7 +121,25 @@ func (w *Writer) open() error {
|
||||||
var resp *raw.Object
|
var resp *raw.Object
|
||||||
err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
|
err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if w.o.userProject != "" {
|
||||||
|
call.UserProject(w.o.userProject)
|
||||||
|
}
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
// If the chunk size is zero, then no chunking is done on the Reader,
|
||||||
|
// which means we cannot retry: the first call will read the data, and if
|
||||||
|
// it fails, there is no way to re-read.
|
||||||
|
if w.ChunkSize == 0 {
|
||||||
resp, err = call.Do()
|
resp, err = call.Do()
|
||||||
|
} else {
|
||||||
|
// We will only retry here if the initial POST, which obtains a URI for
|
||||||
|
// the resumable upload, fails with a retryable error. The upload itself
|
||||||
|
// has its own retry logic.
|
||||||
|
err = runWithRetry(w.ctx, func() error {
|
||||||
|
var err2 error
|
||||||
|
resp, err2 = call.Do()
|
||||||
|
return err2
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.err = err
|
w.err = err
|
||||||
|
@ -106,6 +152,11 @@ func (w *Writer) open() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write appends to w. It implements the io.Writer interface.
|
// Write appends to w. It implements the io.Writer interface.
|
||||||
|
//
|
||||||
|
// Since writes happen asynchronously, Write may return a nil
|
||||||
|
// error even though the write failed (or will fail). Always
|
||||||
|
// use the error returned from Writer.Close to determine if
|
||||||
|
// the upload was successful.
|
||||||
func (w *Writer) Write(p []byte) (n int, err error) {
|
func (w *Writer) Write(p []byte) (n int, err error) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return 0, w.err
|
return 0, w.err
|
||||||
|
@ -120,7 +171,7 @@ func (w *Writer) Write(p []byte) (n int, err error) {
|
||||||
|
|
||||||
// Close completes the write operation and flushes any buffered data.
|
// Close completes the write operation and flushes any buffered data.
|
||||||
// If Close doesn't return an error, metadata about the written object
|
// If Close doesn't return an error, metadata about the written object
|
||||||
// can be retrieved by calling Object.
|
// can be retrieved by calling Attrs.
|
||||||
func (w *Writer) Close() error {
|
func (w *Writer) Close() error {
|
||||||
if !w.opened {
|
if !w.opened {
|
||||||
if err := w.open(); err != nil {
|
if err := w.open(); err != nil {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (C) 2013 Blake Mizerany
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,292 @@
|
||||||
|
// Package quantile computes approximate quantiles over an unbounded data
|
||||||
|
// stream within low memory and CPU bounds.
|
||||||
|
//
|
||||||
|
// A small amount of accuracy is traded to achieve the above properties.
|
||||||
|
//
|
||||||
|
// Multiple streams can be merged before calling Query to generate a single set
|
||||||
|
// of results. This is meaningful when the streams represent the same type of
|
||||||
|
// data. See Merge and Samples.
|
||||||
|
//
|
||||||
|
// For more detailed information about the algorithm used, see:
|
||||||
|
//
|
||||||
|
// Effective Computation of Biased Quantiles over Data Streams
|
||||||
|
//
|
||||||
|
// http://www.cs.rutgers.edu/~muthu/bquant.pdf
|
||||||
|
package quantile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sample holds an observed value and meta information for compression. JSON
|
||||||
|
// tags have been added for convenience.
|
||||||
|
type Sample struct {
|
||||||
|
Value float64 `json:",string"`
|
||||||
|
Width float64 `json:",string"`
|
||||||
|
Delta float64 `json:",string"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samples represents a slice of samples. It implements sort.Interface.
|
||||||
|
type Samples []Sample
|
||||||
|
|
||||||
|
func (a Samples) Len() int { return len(a) }
|
||||||
|
func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
|
||||||
|
func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
|
type invariant func(s *stream, r float64) float64
|
||||||
|
|
||||||
|
// NewLowBiased returns an initialized Stream for low-biased quantiles
|
||||||
|
// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
|
||||||
|
// error guarantees can still be given even for the lower ranks of the data
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// The provided epsilon is a relative error, i.e. the true quantile of a value
|
||||||
|
// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
|
||||||
|
//
|
||||||
|
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
|
||||||
|
// properties.
|
||||||
|
func NewLowBiased(epsilon float64) *Stream {
|
||||||
|
ƒ := func(s *stream, r float64) float64 {
|
||||||
|
return 2 * epsilon * r
|
||||||
|
}
|
||||||
|
return newStream(ƒ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHighBiased returns an initialized Stream for high-biased quantiles
|
||||||
|
// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
|
||||||
|
// error guarantees can still be given even for the higher ranks of the data
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// The provided epsilon is a relative error, i.e. the true quantile of a value
|
||||||
|
// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
|
||||||
|
//
|
||||||
|
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
|
||||||
|
// properties.
|
||||||
|
func NewHighBiased(epsilon float64) *Stream {
|
||||||
|
ƒ := func(s *stream, r float64) float64 {
|
||||||
|
return 2 * epsilon * (s.n - r)
|
||||||
|
}
|
||||||
|
return newStream(ƒ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTargeted returns an initialized Stream concerned with a particular set of
|
||||||
|
// quantile values that are supplied a priori. Knowing these a priori reduces
|
||||||
|
// space and computation time. The targets map maps the desired quantiles to
|
||||||
|
// their absolute errors, i.e. the true quantile of a value returned by a query
|
||||||
|
// is guaranteed to be within (Quantile±Epsilon).
|
||||||
|
//
|
||||||
|
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
|
||||||
|
func NewTargeted(targets map[float64]float64) *Stream {
|
||||||
|
ƒ := func(s *stream, r float64) float64 {
|
||||||
|
var m = math.MaxFloat64
|
||||||
|
var f float64
|
||||||
|
for quantile, epsilon := range targets {
|
||||||
|
if quantile*s.n <= r {
|
||||||
|
f = (2 * epsilon * r) / quantile
|
||||||
|
} else {
|
||||||
|
f = (2 * epsilon * (s.n - r)) / (1 - quantile)
|
||||||
|
}
|
||||||
|
if f < m {
|
||||||
|
m = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
return newStream(ƒ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream computes quantiles for a stream of float64s. It is not thread-safe by
|
||||||
|
// design. Take care when using across multiple goroutines.
|
||||||
|
type Stream struct {
|
||||||
|
*stream
|
||||||
|
b Samples
|
||||||
|
sorted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStream(ƒ invariant) *Stream {
|
||||||
|
x := &stream{ƒ: ƒ}
|
||||||
|
return &Stream{x, make(Samples, 0, 500), true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert inserts v into the stream.
|
||||||
|
func (s *Stream) Insert(v float64) {
|
||||||
|
s.insert(Sample{Value: v, Width: 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) insert(sample Sample) {
|
||||||
|
s.b = append(s.b, sample)
|
||||||
|
s.sorted = false
|
||||||
|
if len(s.b) == cap(s.b) {
|
||||||
|
s.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query returns the computed qth percentiles value. If s was created with
|
||||||
|
// NewTargeted, and q is not in the set of quantiles provided a priori, Query
|
||||||
|
// will return an unspecified result.
|
||||||
|
func (s *Stream) Query(q float64) float64 {
|
||||||
|
if !s.flushed() {
|
||||||
|
// Fast path when there hasn't been enough data for a flush;
|
||||||
|
// this also yields better accuracy for small sets of data.
|
||||||
|
l := len(s.b)
|
||||||
|
if l == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
i := int(math.Ceil(float64(l) * q))
|
||||||
|
if i > 0 {
|
||||||
|
i -= 1
|
||||||
|
}
|
||||||
|
s.maybeSort()
|
||||||
|
return s.b[i].Value
|
||||||
|
}
|
||||||
|
s.flush()
|
||||||
|
return s.stream.query(q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges samples into the underlying streams samples. This is handy when
|
||||||
|
// merging multiple streams from separate threads, database shards, etc.
|
||||||
|
//
|
||||||
|
// ATTENTION: This method is broken and does not yield correct results. The
|
||||||
|
// underlying algorithm is not capable of merging streams correctly.
|
||||||
|
func (s *Stream) Merge(samples Samples) {
|
||||||
|
sort.Sort(samples)
|
||||||
|
s.stream.merge(samples)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset reinitializes and clears the list reusing the samples buffer memory.
|
||||||
|
func (s *Stream) Reset() {
|
||||||
|
s.stream.reset()
|
||||||
|
s.b = s.b[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samples returns stream samples held by s.
|
||||||
|
func (s *Stream) Samples() Samples {
|
||||||
|
if !s.flushed() {
|
||||||
|
return s.b
|
||||||
|
}
|
||||||
|
s.flush()
|
||||||
|
return s.stream.samples()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the total number of samples observed in the stream
|
||||||
|
// since initialization.
|
||||||
|
func (s *Stream) Count() int {
|
||||||
|
return len(s.b) + s.stream.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) flush() {
|
||||||
|
s.maybeSort()
|
||||||
|
s.stream.merge(s.b)
|
||||||
|
s.b = s.b[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) maybeSort() {
|
||||||
|
if !s.sorted {
|
||||||
|
s.sorted = true
|
||||||
|
sort.Sort(s.b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) flushed() bool {
|
||||||
|
return len(s.stream.l) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type stream struct {
|
||||||
|
n float64
|
||||||
|
l []Sample
|
||||||
|
ƒ invariant
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) reset() {
|
||||||
|
s.l = s.l[:0]
|
||||||
|
s.n = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) insert(v float64) {
|
||||||
|
s.merge(Samples{{v, 1, 0}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) merge(samples Samples) {
|
||||||
|
// TODO(beorn7): This tries to merge not only individual samples, but
|
||||||
|
// whole summaries. The paper doesn't mention merging summaries at
|
||||||
|
// all. Unittests show that the merging is inaccurate. Find out how to
|
||||||
|
// do merges properly.
|
||||||
|
var r float64
|
||||||
|
i := 0
|
||||||
|
for _, sample := range samples {
|
||||||
|
for ; i < len(s.l); i++ {
|
||||||
|
c := s.l[i]
|
||||||
|
if c.Value > sample.Value {
|
||||||
|
// Insert at position i.
|
||||||
|
s.l = append(s.l, Sample{})
|
||||||
|
copy(s.l[i+1:], s.l[i:])
|
||||||
|
s.l[i] = Sample{
|
||||||
|
sample.Value,
|
||||||
|
sample.Width,
|
||||||
|
math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
|
||||||
|
// TODO(beorn7): How to calculate delta correctly?
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
goto inserted
|
||||||
|
}
|
||||||
|
r += c.Width
|
||||||
|
}
|
||||||
|
s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
|
||||||
|
i++
|
||||||
|
inserted:
|
||||||
|
s.n += sample.Width
|
||||||
|
r += sample.Width
|
||||||
|
}
|
||||||
|
s.compress()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) count() int {
|
||||||
|
return int(s.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) query(q float64) float64 {
|
||||||
|
t := math.Ceil(q * s.n)
|
||||||
|
t += math.Ceil(s.ƒ(s, t) / 2)
|
||||||
|
p := s.l[0]
|
||||||
|
var r float64
|
||||||
|
for _, c := range s.l[1:] {
|
||||||
|
r += p.Width
|
||||||
|
if r+c.Width+c.Delta > t {
|
||||||
|
return p.Value
|
||||||
|
}
|
||||||
|
p = c
|
||||||
|
}
|
||||||
|
return p.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) compress() {
|
||||||
|
if len(s.l) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
x := s.l[len(s.l)-1]
|
||||||
|
xi := len(s.l) - 1
|
||||||
|
r := s.n - 1 - x.Width
|
||||||
|
|
||||||
|
for i := len(s.l) - 2; i >= 0; i-- {
|
||||||
|
c := s.l[i]
|
||||||
|
if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
|
||||||
|
x.Width += c.Width
|
||||||
|
s.l[xi] = x
|
||||||
|
// Remove element at i.
|
||||||
|
copy(s.l[i:], s.l[i+1:])
|
||||||
|
s.l = s.l[:len(s.l)-1]
|
||||||
|
xi -= 1
|
||||||
|
} else {
|
||||||
|
x = c
|
||||||
|
xi = i
|
||||||
|
}
|
||||||
|
r -= c.Width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stream) samples() Samples {
|
||||||
|
samples := make(Samples, len(s.l))
|
||||||
|
copy(samples, s.l)
|
||||||
|
return samples
|
||||||
|
}
|
|
@ -110,7 +110,7 @@ func New() *PatternServeMux {
|
||||||
// described above.
|
// described above.
|
||||||
func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
for _, ph := range p.handlers[r.Method] {
|
for _, ph := range p.handlers[r.Method] {
|
||||||
if params, ok := ph.try(r.URL.Path); ok {
|
if params, ok := ph.try(r.URL.EscapedPath()); ok {
|
||||||
if len(params) > 0 && !ph.redirect {
|
if len(params) > 0 && !ph.redirect {
|
||||||
r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery
|
r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ph := range handlers {
|
for _, ph := range handlers {
|
||||||
if _, ok := ph.try(r.URL.Path); ok {
|
if _, ok := ph.try(r.URL.EscapedPath()); ok {
|
||||||
allowed = append(allowed, meth)
|
allowed = append(allowed, meth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,11 @@ func (ph *patHandler) try(path string) (url.Values, bool) {
|
||||||
var nextc byte
|
var nextc byte
|
||||||
name, nextc, j = match(ph.pat, isAlnum, j+1)
|
name, nextc, j = match(ph.pat, isAlnum, j+1)
|
||||||
val, _, i = match(path, matchPart(nextc), i)
|
val, _, i = match(path, matchPart(nextc), i)
|
||||||
p.Add(":"+name, val)
|
escval, err := url.QueryUnescape(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
p.Add(":"+name, escval)
|
||||||
case path[i] == ph.pat[j]:
|
case path[i] == ph.pat[j]:
|
||||||
i++
|
i++
|
||||||
j++
|
j++
|
||||||
|
|
|
@ -2,7 +2,7 @@ ISC License
|
||||||
|
|
||||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
copyright notice and this permission notice appear in all copies.
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ var (
|
||||||
// after commit 82f48826c6c7 which changed the format again to mirror
|
// after commit 82f48826c6c7 which changed the format again to mirror
|
||||||
// the original format. Code in the init function updates these offsets
|
// the original format. Code in the init function updates these offsets
|
||||||
// as necessary.
|
// as necessary.
|
||||||
offsetPtr = uintptr(ptrSize)
|
offsetPtr = ptrSize
|
||||||
offsetScalar = uintptr(0)
|
offsetScalar = uintptr(0)
|
||||||
offsetFlag = uintptr(ptrSize * 2)
|
offsetFlag = ptrSize * 2
|
||||||
|
|
||||||
// flagKindWidth and flagKindShift indicate various bits that the
|
// flagKindWidth and flagKindShift indicate various bits that the
|
||||||
// reflect package uses internally to track kind information.
|
// reflect package uses internally to track kind information.
|
||||||
|
@ -58,7 +58,7 @@ var (
|
||||||
// changed their positions. Code in the init function updates these
|
// changed their positions. Code in the init function updates these
|
||||||
// flags as necessary.
|
// flags as necessary.
|
||||||
flagKindWidth = uintptr(5)
|
flagKindWidth = uintptr(5)
|
||||||
flagKindShift = uintptr(flagKindWidth - 1)
|
flagKindShift = flagKindWidth - 1
|
||||||
flagRO = uintptr(1 << 0)
|
flagRO = uintptr(1 << 0)
|
||||||
flagIndir = uintptr(1 << 1)
|
flagIndir = uintptr(1 << 1)
|
||||||
)
|
)
|
||||||
|
|
|
@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||||
w.Write(closeParenBytes)
|
w.Write(closeParenBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
|
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||||
// prefix to Writer w.
|
// prefix to Writer w.
|
||||||
func printHexPtr(w io.Writer, p uintptr) {
|
func printHexPtr(w io.Writer, p uintptr) {
|
||||||
// Null pointer.
|
// Null pointer.
|
||||||
|
|
|
@ -35,16 +35,16 @@ var (
|
||||||
|
|
||||||
// cCharRE is a regular expression that matches a cgo char.
|
// cCharRE is a regular expression that matches a cgo char.
|
||||||
// It is used to detect character arrays to hexdump them.
|
// It is used to detect character arrays to hexdump them.
|
||||||
cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
|
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
||||||
|
|
||||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||||
// char. It is used to detect unsigned character arrays to hexdump
|
// char. It is used to detect unsigned character arrays to hexdump
|
||||||
// them.
|
// them.
|
||||||
cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
|
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
||||||
|
|
||||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||||
// It is used to detect uint8_t arrays to hexdump them.
|
// It is used to detect uint8_t arrays to hexdump them.
|
||||||
cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
|
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// dumpState contains information about the state of a dump operation.
|
// dumpState contains information about the state of a dump operation.
|
||||||
|
@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||||
// Display dereferenced value.
|
// Display dereferenced value.
|
||||||
d.w.Write(openParenBytes)
|
d.w.Write(openParenBytes)
|
||||||
switch {
|
switch {
|
||||||
case nilFound == true:
|
case nilFound:
|
||||||
d.w.Write(nilAngleBytes)
|
d.w.Write(nilAngleBytes)
|
||||||
|
|
||||||
case cycleFound == true:
|
case cycleFound:
|
||||||
d.w.Write(circularBytes)
|
d.w.Write(circularBytes)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) {
|
||||||
|
|
||||||
// Display dereferenced value.
|
// Display dereferenced value.
|
||||||
switch {
|
switch {
|
||||||
case nilFound == true:
|
case nilFound:
|
||||||
f.fs.Write(nilAngleBytes)
|
f.fs.Write(nilAngleBytes)
|
||||||
|
|
||||||
case cycleFound == true:
|
case cycleFound:
|
||||||
f.fs.Write(circularShortBytes)
|
f.fs.Write(circularShortBytes)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
glog
|
||||||
|
====
|
||||||
|
|
||||||
|
Leveled execution logs for Go.
|
||||||
|
|
||||||
|
This is an efficient pure Go implementation of leveled logs in the
|
||||||
|
manner of the open source C++ package
|
||||||
|
https://github.com/google/glog
|
||||||
|
|
||||||
|
By binding methods to booleans it is possible to use the log package
|
||||||
|
without paying the expense of evaluating the arguments to the log.
|
||||||
|
Through the -vmodule flag, the package also provides fine-grained
|
||||||
|
control over logging at the file level.
|
||||||
|
|
||||||
|
The comment from glog.go introduces the ideas:
|
||||||
|
|
||||||
|
Package glog implements logging analogous to the Google-internal
|
||||||
|
C++ INFO/ERROR/V setup. It provides functions Info, Warning,
|
||||||
|
Error, Fatal, plus formatting variants such as Infof. It
|
||||||
|
also provides V-style logging controlled by the -v and
|
||||||
|
-vmodule=file=2 flags.
|
||||||
|
|
||||||
|
Basic examples:
|
||||||
|
|
||||||
|
glog.Info("Prepare to repel boarders")
|
||||||
|
|
||||||
|
glog.Fatalf("Initialization failed: %s", err)
|
||||||
|
|
||||||
|
See the documentation for the V function for an explanation
|
||||||
|
of these examples:
|
||||||
|
|
||||||
|
if glog.V(2) {
|
||||||
|
glog.Info("Starting transaction...")
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(2).Infoln("Processed", nItems, "elements")
|
||||||
|
|
||||||
|
|
||||||
|
The repository contains an open source version of the log package
|
||||||
|
used inside Google. The master copy of the source lives inside
|
||||||
|
Google, not here. The code in this repo is for export only and is not itself
|
||||||
|
under development. Feature requests will be ignored.
|
||||||
|
|
||||||
|
Send bug reports to golang-nuts@googlegroups.com.
|
|
@ -17,6 +17,7 @@ package gomock
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,8 +27,9 @@ type Call struct {
|
||||||
|
|
||||||
receiver interface{} // the receiver of the method call
|
receiver interface{} // the receiver of the method call
|
||||||
method string // the name of the method
|
method string // the name of the method
|
||||||
|
methodType reflect.Type // the type of the method
|
||||||
args []Matcher // the args
|
args []Matcher // the args
|
||||||
rets []interface{} // the return values (if any)
|
origin string // file and line number of call setup
|
||||||
|
|
||||||
preReqs []*Call // prerequisite calls
|
preReqs []*Call // prerequisite calls
|
||||||
|
|
||||||
|
@ -36,9 +38,44 @@ type Call struct {
|
||||||
|
|
||||||
numCalls int // actual number made
|
numCalls int // actual number made
|
||||||
|
|
||||||
// Actions
|
// actions are called when this Call is called. Each action gets the args and
|
||||||
doFunc reflect.Value
|
// can set the return values by returning a non-nil slice. Actions run in the
|
||||||
setArgs map[int]reflect.Value
|
// order they are created.
|
||||||
|
actions []func([]interface{}) []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCall creates a *Call. It requires the method type in order to support
|
||||||
|
// unexported methods.
|
||||||
|
func newCall(t TestReporter, receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
|
||||||
|
if h, ok := t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check arity, types.
|
||||||
|
margs := make([]Matcher, len(args))
|
||||||
|
for i, arg := range args {
|
||||||
|
if m, ok := arg.(Matcher); ok {
|
||||||
|
margs[i] = m
|
||||||
|
} else if arg == nil {
|
||||||
|
// Handle nil specially so that passing a nil interface value
|
||||||
|
// will match the typed nils of concrete args.
|
||||||
|
margs[i] = Nil()
|
||||||
|
} else {
|
||||||
|
margs[i] = Eq(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
origin := callerInfo(3)
|
||||||
|
actions := []func([]interface{}) []interface{}{func([]interface{}) []interface{} {
|
||||||
|
// Synthesize the zero value for each of the return args' types.
|
||||||
|
rets := make([]interface{}, methodType.NumOut())
|
||||||
|
for i := 0; i < methodType.NumOut(); i++ {
|
||||||
|
rets[i] = reflect.Zero(methodType.Out(i)).Interface()
|
||||||
|
}
|
||||||
|
return rets
|
||||||
|
}}
|
||||||
|
return &Call{t: t, receiver: receiver, method: method, methodType: methodType,
|
||||||
|
args: margs, origin: origin, minCalls: 1, maxCalls: 1, actions: actions}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyTimes allows the expectation to be called 0 or more times
|
// AnyTimes allows the expectation to be called 0 or more times
|
||||||
|
@ -67,19 +104,69 @@ func (c *Call) MaxTimes(n int) *Call {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do declares the action to run when the call is matched.
|
// DoAndReturn declares the action to run when the call is matched.
|
||||||
|
// The return values from this function are returned by the mocked function.
|
||||||
// It takes an interface{} argument to support n-arity functions.
|
// It takes an interface{} argument to support n-arity functions.
|
||||||
func (c *Call) Do(f interface{}) *Call {
|
func (c *Call) DoAndReturn(f interface{}) *Call {
|
||||||
// TODO: Check arity and types here, rather than dying badly elsewhere.
|
// TODO: Check arity and types here, rather than dying badly elsewhere.
|
||||||
c.doFunc = reflect.ValueOf(f)
|
v := reflect.ValueOf(f)
|
||||||
|
|
||||||
|
c.addAction(func(args []interface{}) []interface{} {
|
||||||
|
vargs := make([]reflect.Value, len(args))
|
||||||
|
ft := v.Type()
|
||||||
|
for i := 0; i < len(args); i++ {
|
||||||
|
if args[i] != nil {
|
||||||
|
vargs[i] = reflect.ValueOf(args[i])
|
||||||
|
} else {
|
||||||
|
// Use the zero value for the arg.
|
||||||
|
vargs[i] = reflect.Zero(ft.In(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vrets := v.Call(vargs)
|
||||||
|
rets := make([]interface{}, len(vrets))
|
||||||
|
for i, ret := range vrets {
|
||||||
|
rets[i] = ret.Interface()
|
||||||
|
}
|
||||||
|
return rets
|
||||||
|
})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do declares the action to run when the call is matched. The function's
|
||||||
|
// return values are ignored to retain backward compatibility. To use the
|
||||||
|
// return values call DoAndReturn.
|
||||||
|
// It takes an interface{} argument to support n-arity functions.
|
||||||
|
func (c *Call) Do(f interface{}) *Call {
|
||||||
|
// TODO: Check arity and types here, rather than dying badly elsewhere.
|
||||||
|
v := reflect.ValueOf(f)
|
||||||
|
|
||||||
|
c.addAction(func(args []interface{}) []interface{} {
|
||||||
|
vargs := make([]reflect.Value, len(args))
|
||||||
|
ft := v.Type()
|
||||||
|
for i := 0; i < len(args); i++ {
|
||||||
|
if args[i] != nil {
|
||||||
|
vargs[i] = reflect.ValueOf(args[i])
|
||||||
|
} else {
|
||||||
|
// Use the zero value for the arg.
|
||||||
|
vargs[i] = reflect.Zero(ft.In(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.Call(vargs)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return declares the values to be returned by the mocked function call.
|
||||||
func (c *Call) Return(rets ...interface{}) *Call {
|
func (c *Call) Return(rets ...interface{}) *Call {
|
||||||
mt := c.methodType()
|
if h, ok := c.t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
mt := c.methodType
|
||||||
if len(rets) != mt.NumOut() {
|
if len(rets) != mt.NumOut() {
|
||||||
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d",
|
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
|
||||||
c.receiver, c.method, len(rets), mt.NumOut())
|
c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
|
||||||
}
|
}
|
||||||
for i, ret := range rets {
|
for i, ret := range rets {
|
||||||
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
|
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
|
||||||
|
@ -90,8 +177,8 @@ func (c *Call) Return(rets ...interface{}) *Call {
|
||||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||||
// ok
|
// ok
|
||||||
default:
|
default:
|
||||||
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable",
|
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
|
||||||
i, c.receiver, c.method, want)
|
i, c.receiver, c.method, want, c.origin)
|
||||||
}
|
}
|
||||||
} else if got.AssignableTo(want) {
|
} else if got.AssignableTo(want) {
|
||||||
// Assignable type relation. Make the assignment now so that the generated code
|
// Assignable type relation. Make the assignment now so that the generated code
|
||||||
|
@ -100,31 +187,38 @@ func (c *Call) Return(rets ...interface{}) *Call {
|
||||||
v.Set(reflect.ValueOf(ret))
|
v.Set(reflect.ValueOf(ret))
|
||||||
rets[i] = v.Interface()
|
rets[i] = v.Interface()
|
||||||
} else {
|
} else {
|
||||||
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v",
|
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
|
||||||
i, c.receiver, c.method, got, want)
|
i, c.receiver, c.method, got, want, c.origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.rets = rets
|
c.addAction(func([]interface{}) []interface{} {
|
||||||
|
return rets
|
||||||
|
})
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Times declares the exact number of times a function call is expected to be executed.
|
||||||
func (c *Call) Times(n int) *Call {
|
func (c *Call) Times(n int) *Call {
|
||||||
c.minCalls, c.maxCalls = n, n
|
c.minCalls, c.maxCalls = n, n
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetArg declares an action that will set the nth argument's value,
|
// SetArg declares an action that will set the nth argument's value,
|
||||||
// indirected through a pointer.
|
// indirected through a pointer. Or, in the case of a slice, SetArg
|
||||||
|
// will copy value's elements into the nth argument.
|
||||||
func (c *Call) SetArg(n int, value interface{}) *Call {
|
func (c *Call) SetArg(n int, value interface{}) *Call {
|
||||||
if c.setArgs == nil {
|
if h, ok := c.t.(testHelper); ok {
|
||||||
c.setArgs = make(map[int]reflect.Value)
|
h.Helper()
|
||||||
}
|
}
|
||||||
mt := c.methodType()
|
|
||||||
|
mt := c.methodType
|
||||||
// TODO: This will break on variadic methods.
|
// TODO: This will break on variadic methods.
|
||||||
// We will need to check those at invocation time.
|
// We will need to check those at invocation time.
|
||||||
if n < 0 || n >= mt.NumIn() {
|
if n < 0 || n >= mt.NumIn() {
|
||||||
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn())
|
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
|
||||||
|
n, mt.NumIn(), c.origin)
|
||||||
}
|
}
|
||||||
// Permit setting argument through an interface.
|
// Permit setting argument through an interface.
|
||||||
// In the interface case, we don't (nay, can't) check the type here.
|
// In the interface case, we don't (nay, can't) check the type here.
|
||||||
|
@ -133,14 +227,28 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
dt := at.Elem()
|
dt := at.Elem()
|
||||||
if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
|
if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
|
||||||
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt)
|
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
|
||||||
|
n, vt, dt, c.origin)
|
||||||
}
|
}
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
case reflect.Slice:
|
||||||
|
// nothing to do
|
||||||
default:
|
default:
|
||||||
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at)
|
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
|
||||||
|
n, at, c.origin)
|
||||||
}
|
}
|
||||||
c.setArgs[n] = reflect.ValueOf(value)
|
|
||||||
|
c.addAction(func(args []interface{}) []interface{} {
|
||||||
|
v := reflect.ValueOf(value)
|
||||||
|
switch reflect.TypeOf(args[n]).Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
setSlice(args[n], v)
|
||||||
|
default:
|
||||||
|
reflect.ValueOf(args[n]).Elem().Set(v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,19 +264,22 @@ func (c *Call) isPreReq(other *Call) bool {
|
||||||
|
|
||||||
// After declares that the call may only match after preReq has been exhausted.
|
// After declares that the call may only match after preReq has been exhausted.
|
||||||
func (c *Call) After(preReq *Call) *Call {
|
func (c *Call) After(preReq *Call) *Call {
|
||||||
|
if h, ok := c.t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == preReq {
|
||||||
|
c.t.Fatalf("A call isn't allowed to be its own prerequisite")
|
||||||
|
}
|
||||||
if preReq.isPreReq(c) {
|
if preReq.isPreReq(c) {
|
||||||
msg := fmt.Sprintf(
|
c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
|
||||||
"Loop in call order: %v is a prerequisite to %v (possibly indirectly).",
|
|
||||||
c, preReq,
|
|
||||||
)
|
|
||||||
panic(msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.preReqs = append(c.preReqs, preReq)
|
c.preReqs = append(c.preReqs, preReq)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff the minimum number of calls have been made.
|
// Returns true if the minimum number of calls have been made.
|
||||||
func (c *Call) satisfied() bool {
|
func (c *Call) satisfied() bool {
|
||||||
return c.numCalls >= c.minCalls
|
return c.numCalls >= c.minCalls
|
||||||
}
|
}
|
||||||
|
@ -184,31 +295,105 @@ func (c *Call) String() string {
|
||||||
args[i] = arg.String()
|
args[i] = arg.String()
|
||||||
}
|
}
|
||||||
arguments := strings.Join(args, ", ")
|
arguments := strings.Join(args, ", ")
|
||||||
return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments)
|
return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests if the given call matches the expected call.
|
// Tests if the given call matches the expected call.
|
||||||
func (c *Call) matches(args []interface{}) bool {
|
// If yes, returns nil. If no, returns error with message explaining why it does not match.
|
||||||
|
func (c *Call) matches(args []interface{}) error {
|
||||||
|
if !c.methodType.IsVariadic() {
|
||||||
if len(args) != len(c.args) {
|
if len(args) != len(c.args) {
|
||||||
return false
|
return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
|
||||||
|
c.origin, len(args), len(c.args))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, m := range c.args {
|
for i, m := range c.args {
|
||||||
if !m.Matches(args[i]) {
|
if !m.Matches(args[i]) {
|
||||||
return false
|
return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
|
||||||
|
c.origin, strconv.Itoa(i), args[i], m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(c.args) < c.methodType.NumIn()-1 {
|
||||||
|
return fmt.Errorf("Expected call at %s has the wrong number of matchers. Got: %d, want: %d",
|
||||||
|
c.origin, len(c.args), c.methodType.NumIn()-1)
|
||||||
|
}
|
||||||
|
if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
|
||||||
|
return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
|
||||||
|
c.origin, len(args), len(c.args))
|
||||||
|
}
|
||||||
|
if len(args) < len(c.args)-1 {
|
||||||
|
return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
|
||||||
|
c.origin, len(args), len(c.args)-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range c.args {
|
||||||
|
if i == len(c.args)-1 {
|
||||||
|
// The last arg has a possibility of a variadic argument, so let it branch
|
||||||
|
|
||||||
|
// sample: Foo(a int, b int, c ...int)
|
||||||
|
|
||||||
|
if len(c.args) == len(args) {
|
||||||
|
if m.Matches(args[i]) {
|
||||||
|
// Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
|
||||||
|
// Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
|
||||||
|
// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
|
||||||
|
// Got Foo(a, b) want Foo(matcherA, matcherB)
|
||||||
|
// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The number of actual args don't match the number of matchers.
|
||||||
|
// If this function still matches it is because the last matcher
|
||||||
|
// matches all the remaining arguments or the lack of any.
|
||||||
|
// Convert the remaining arguments, if any, into a slice of the
|
||||||
|
// expected type.
|
||||||
|
vargsType := c.methodType.In(c.methodType.NumIn() - 1)
|
||||||
|
vargs := reflect.MakeSlice(vargsType, 0, len(args)-i)
|
||||||
|
for _, arg := range args[i:] {
|
||||||
|
vargs = reflect.Append(vargs, reflect.ValueOf(arg))
|
||||||
|
}
|
||||||
|
if m.Matches(vargs.Interface()) {
|
||||||
|
// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
|
||||||
|
// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
|
||||||
|
// Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
|
||||||
|
// Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Wrong number of matchers or not match. Fail.
|
||||||
|
// Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
|
||||||
|
// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
|
||||||
|
// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
|
||||||
|
// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
|
||||||
|
// Got Foo(a, b, c) want Foo(matcherA, matcherB)
|
||||||
|
return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
|
||||||
|
c.origin, strconv.Itoa(i), args[i:], c.args[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.Matches(args[i]) {
|
||||||
|
return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
|
||||||
|
c.origin, strconv.Itoa(i), args[i], m)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all prerequisite calls have been satisfied.
|
// Check that all prerequisite calls have been satisfied.
|
||||||
for _, preReqCall := range c.preReqs {
|
for _, preReqCall := range c.preReqs {
|
||||||
if !preReqCall.satisfied() {
|
if !preReqCall.satisfied() {
|
||||||
return false
|
return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
|
||||||
|
c.origin, preReqCall, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
// Check that the call is not exhausted.
|
||||||
|
if c.exhausted() {
|
||||||
|
return fmt.Errorf("Expected call at %s has already been called the max number of times.", c.origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// dropPrereqs tells the expected Call to not re-check prerequite calls any
|
// dropPrereqs tells the expected Call to not re-check prerequisite calls any
|
||||||
// longer, and to return its current set.
|
// longer, and to return its current set.
|
||||||
func (c *Call) dropPrereqs() (preReqs []*Call) {
|
func (c *Call) dropPrereqs() (preReqs []*Call) {
|
||||||
preReqs = c.preReqs
|
preReqs = c.preReqs
|
||||||
|
@ -216,48 +401,9 @@ func (c *Call) dropPrereqs() (preReqs []*Call) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
|
func (c *Call) call(args []interface{}) []func([]interface{}) []interface{} {
|
||||||
c.numCalls++
|
c.numCalls++
|
||||||
|
return c.actions
|
||||||
// Actions
|
|
||||||
if c.doFunc.IsValid() {
|
|
||||||
doArgs := make([]reflect.Value, len(args))
|
|
||||||
ft := c.doFunc.Type()
|
|
||||||
for i := 0; i < ft.NumIn(); i++ {
|
|
||||||
if args[i] != nil {
|
|
||||||
doArgs[i] = reflect.ValueOf(args[i])
|
|
||||||
} else {
|
|
||||||
// Use the zero value for the arg.
|
|
||||||
doArgs[i] = reflect.Zero(ft.In(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
action = func() { c.doFunc.Call(doArgs) }
|
|
||||||
}
|
|
||||||
for n, v := range c.setArgs {
|
|
||||||
reflect.ValueOf(args[n]).Elem().Set(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
rets = c.rets
|
|
||||||
if rets == nil {
|
|
||||||
// Synthesize the zero value for each of the return args' types.
|
|
||||||
mt := c.methodType()
|
|
||||||
rets = make([]interface{}, mt.NumOut())
|
|
||||||
for i := 0; i < mt.NumOut(); i++ {
|
|
||||||
rets[i] = reflect.Zero(mt.Out(i)).Interface()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Call) methodType() reflect.Type {
|
|
||||||
recv := reflect.ValueOf(c.receiver)
|
|
||||||
for i := 0; i < recv.Type().NumMethod(); i++ {
|
|
||||||
if recv.Type().Method(i).Name == c.method {
|
|
||||||
return recv.Method(i).Type()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("gomock: failed finding method %s on %T", c.method, c.receiver))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InOrder declares that the given calls should occur in order.
|
// InOrder declares that the given calls should occur in order.
|
||||||
|
@ -266,3 +412,14 @@ func InOrder(calls ...*Call) {
|
||||||
calls[i].After(calls[i-1])
|
calls[i].After(calls[i-1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSlice(arg interface{}, v reflect.Value) {
|
||||||
|
va := reflect.ValueOf(arg)
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
va.Index(i).Set(v.Index(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Call) addAction(action func([]interface{}) []interface{}) {
|
||||||
|
c.actions = append(c.actions, action)
|
||||||
|
}
|
||||||
|
|
|
@ -14,63 +14,95 @@
|
||||||
|
|
||||||
package gomock
|
package gomock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// callSet represents a set of expected calls, indexed by receiver and method
|
// callSet represents a set of expected calls, indexed by receiver and method
|
||||||
// name.
|
// name.
|
||||||
type callSet map[interface{}]map[string][]*Call
|
type callSet struct {
|
||||||
|
// Calls that are still expected.
|
||||||
|
expected map[callSetKey][]*Call
|
||||||
|
// Calls that have been exhausted.
|
||||||
|
exhausted map[callSetKey][]*Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// callSetKey is the key in the maps in callSet
|
||||||
|
type callSetKey struct {
|
||||||
|
receiver interface{}
|
||||||
|
fname string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCallSet() *callSet {
|
||||||
|
return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)}
|
||||||
|
}
|
||||||
|
|
||||||
// Add adds a new expected call.
|
// Add adds a new expected call.
|
||||||
func (cs callSet) Add(call *Call) {
|
func (cs callSet) Add(call *Call) {
|
||||||
methodMap, ok := cs[call.receiver]
|
key := callSetKey{call.receiver, call.method}
|
||||||
if !ok {
|
m := cs.expected
|
||||||
methodMap = make(map[string][]*Call)
|
if call.exhausted() {
|
||||||
cs[call.receiver] = methodMap
|
m = cs.exhausted
|
||||||
}
|
}
|
||||||
methodMap[call.method] = append(methodMap[call.method], call)
|
m[key] = append(m[key], call)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes an expected call.
|
// Remove removes an expected call.
|
||||||
func (cs callSet) Remove(call *Call) {
|
func (cs callSet) Remove(call *Call) {
|
||||||
methodMap, ok := cs[call.receiver]
|
key := callSetKey{call.receiver, call.method}
|
||||||
if !ok {
|
calls := cs.expected[key]
|
||||||
return
|
for i, c := range calls {
|
||||||
}
|
|
||||||
sl := methodMap[call.method]
|
|
||||||
for i, c := range sl {
|
|
||||||
if c == call {
|
if c == call {
|
||||||
// quick removal; we don't need to maintain call order
|
// maintain order for remaining calls
|
||||||
if len(sl) > 1 {
|
cs.expected[key] = append(calls[:i], calls[i+1:]...)
|
||||||
sl[i] = sl[len(sl)-1]
|
cs.exhausted[key] = append(cs.exhausted[key], call)
|
||||||
}
|
|
||||||
methodMap[call.method] = sl[:len(sl)-1]
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindMatch searches for a matching call. Returns nil if no call matched.
|
// FindMatch searches for a matching call. Returns error with explanation message if no call matched.
|
||||||
func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) *Call {
|
func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) {
|
||||||
methodMap, ok := cs[receiver]
|
key := callSetKey{receiver, method}
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
calls, ok := methodMap[method]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search through the unordered set of calls expected on a method on a
|
// Search through the expected calls.
|
||||||
// receiver.
|
expected := cs.expected[key]
|
||||||
for _, call := range calls {
|
var callsErrors bytes.Buffer
|
||||||
// A call should not normally still be here if exhausted,
|
for _, call := range expected {
|
||||||
// but it can happen if, for instance, .Times(0) was used.
|
err := call.matches(args)
|
||||||
// Pretend the call doesn't match.
|
if err != nil {
|
||||||
if call.exhausted() {
|
fmt.Fprintf(&callsErrors, "\n%v", err)
|
||||||
continue
|
} else {
|
||||||
}
|
return call, nil
|
||||||
if call.matches(args) {
|
|
||||||
return call
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// If we haven't found a match then search through the exhausted calls so we
|
||||||
|
// get useful error messages.
|
||||||
|
exhausted := cs.exhausted[key]
|
||||||
|
for _, call := range exhausted {
|
||||||
|
if err := call.matches(args); err != nil {
|
||||||
|
fmt.Fprintf(&callsErrors, "\n%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expected)+len(exhausted) == 0 {
|
||||||
|
fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf(callsErrors.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failures returns the calls that are not satisfied.
|
||||||
|
func (cs callSet) Failures() []*Call {
|
||||||
|
failures := make([]*Call, 0, len(cs.expected))
|
||||||
|
for _, calls := range cs.expected {
|
||||||
|
for _, call := range calls {
|
||||||
|
if !call.satisfied() {
|
||||||
|
failures = append(failures, call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return failures
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,13 @@
|
||||||
// - Handle different argument/return types (e.g. ..., chan, map, interface).
|
// - Handle different argument/return types (e.g. ..., chan, map, interface).
|
||||||
package gomock
|
package gomock
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
// A TestReporter is something that can be used to report test failures.
|
// A TestReporter is something that can be used to report test failures.
|
||||||
// It is satisfied by the standard library's *testing.T.
|
// It is satisfied by the standard library's *testing.T.
|
||||||
|
@ -70,47 +76,77 @@ type TestReporter interface {
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
t TestReporter
|
t TestReporter
|
||||||
expectedCalls callSet
|
expectedCalls *callSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewController(t TestReporter) *Controller {
|
func NewController(t TestReporter) *Controller {
|
||||||
return &Controller{
|
return &Controller{
|
||||||
t: t,
|
t: t,
|
||||||
expectedCalls: make(callSet),
|
expectedCalls: newCallSet(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cancelReporter struct {
|
||||||
|
t TestReporter
|
||||||
|
cancel func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *cancelReporter) Errorf(format string, args ...interface{}) { r.t.Errorf(format, args...) }
|
||||||
|
func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
|
||||||
|
defer r.cancel()
|
||||||
|
r.t.Fatalf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext returns a new Controller and a Context, which is cancelled on any
|
||||||
|
// fatal failure.
|
||||||
|
func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
return NewController(&cancelReporter{t, cancel}), ctx
|
||||||
|
}
|
||||||
|
|
||||||
func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
|
func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
|
||||||
// TODO: check arity, types.
|
if h, ok := ctrl.t.(testHelper); ok {
|
||||||
margs := make([]Matcher, len(args))
|
h.Helper()
|
||||||
for i, arg := range args {
|
}
|
||||||
if m, ok := arg.(Matcher); ok {
|
|
||||||
margs[i] = m
|
recv := reflect.ValueOf(receiver)
|
||||||
} else if arg == nil {
|
for i := 0; i < recv.Type().NumMethod(); i++ {
|
||||||
// Handle nil specially so that passing a nil interface value
|
if recv.Type().Method(i).Name == method {
|
||||||
// will match the typed nils of concrete args.
|
return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
|
||||||
margs[i] = Nil()
|
|
||||||
} else {
|
|
||||||
margs[i] = Eq(arg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctrl.t.Fatalf("gomock: failed finding method %s on %T", method, receiver)
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
|
||||||
|
if h, ok := ctrl.t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
call := newCall(ctrl.t, receiver, method, methodType, args...)
|
||||||
|
|
||||||
ctrl.mu.Lock()
|
ctrl.mu.Lock()
|
||||||
defer ctrl.mu.Unlock()
|
defer ctrl.mu.Unlock()
|
||||||
|
|
||||||
call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, minCalls: 1, maxCalls: 1}
|
|
||||||
|
|
||||||
ctrl.expectedCalls.Add(call)
|
ctrl.expectedCalls.Add(call)
|
||||||
|
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
|
func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
|
||||||
|
if h, ok := ctrl.t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nest this code so we can use defer to make sure the lock is released.
|
||||||
|
actions := func() []func([]interface{}) []interface{} {
|
||||||
ctrl.mu.Lock()
|
ctrl.mu.Lock()
|
||||||
defer ctrl.mu.Unlock()
|
defer ctrl.mu.Unlock()
|
||||||
|
|
||||||
expected := ctrl.expectedCalls.FindMatch(receiver, method, args)
|
expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
|
||||||
if expected == nil {
|
if err != nil {
|
||||||
ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args)
|
origin := callerInfo(2)
|
||||||
|
ctrl.t.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two things happen here:
|
// Two things happen here:
|
||||||
|
@ -121,25 +157,28 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf
|
||||||
ctrl.expectedCalls.Remove(preReqCall)
|
ctrl.expectedCalls.Remove(preReqCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
rets, action := expected.call(args)
|
actions := expected.call(args)
|
||||||
if expected.exhausted() {
|
if expected.exhausted() {
|
||||||
ctrl.expectedCalls.Remove(expected)
|
ctrl.expectedCalls.Remove(expected)
|
||||||
}
|
}
|
||||||
|
return actions
|
||||||
|
}()
|
||||||
|
|
||||||
// Don't hold the lock while doing the call's action (if any)
|
var rets []interface{}
|
||||||
// so that actions may execute concurrently.
|
for _, action := range actions {
|
||||||
// We use the deferred Unlock to capture any panics that happen above;
|
if r := action(args); r != nil {
|
||||||
// here we add a deferred Lock to balance it.
|
rets = r
|
||||||
ctrl.mu.Unlock()
|
}
|
||||||
defer ctrl.mu.Lock()
|
|
||||||
if action != nil {
|
|
||||||
action()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rets
|
return rets
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *Controller) Finish() {
|
func (ctrl *Controller) Finish() {
|
||||||
|
if h, ok := ctrl.t.(testHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
ctrl.mu.Lock()
|
ctrl.mu.Lock()
|
||||||
defer ctrl.mu.Unlock()
|
defer ctrl.mu.Unlock()
|
||||||
|
|
||||||
|
@ -150,18 +189,23 @@ func (ctrl *Controller) Finish() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all remaining expected calls are satisfied.
|
// Check that all remaining expected calls are satisfied.
|
||||||
failures := false
|
failures := ctrl.expectedCalls.Failures()
|
||||||
for _, methodMap := range ctrl.expectedCalls {
|
for _, call := range failures {
|
||||||
for _, calls := range methodMap {
|
|
||||||
for _, call := range calls {
|
|
||||||
if !call.satisfied() {
|
|
||||||
ctrl.t.Errorf("missing call(s) to %v", call)
|
ctrl.t.Errorf("missing call(s) to %v", call)
|
||||||
failures = true
|
|
||||||
}
|
}
|
||||||
}
|
if len(failures) != 0 {
|
||||||
}
|
|
||||||
}
|
|
||||||
if failures {
|
|
||||||
ctrl.t.Fatalf("aborting test due to missing call(s)")
|
ctrl.t.Fatalf("aborting test due to missing call(s)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func callerInfo(skip int) string {
|
||||||
|
if _, file, line, ok := runtime.Caller(skip + 1); ok {
|
||||||
|
return fmt.Sprintf("%s:%d", file, line)
|
||||||
|
}
|
||||||
|
return "unknown file"
|
||||||
|
}
|
||||||
|
|
||||||
|
type testHelper interface {
|
||||||
|
TestReporter
|
||||||
|
Helper()
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//go:generate mockgen -destination mock_matcher/mock_matcher.go github.com/golang/mock/gomock Matcher
|
||||||
|
|
||||||
// Copyright 2010 Google Inc.
|
// Copyright 2010 Google Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -22,7 +24,7 @@ import (
|
||||||
// A Matcher is a representation of a class of values.
|
// A Matcher is a representation of a class of values.
|
||||||
// It is used to represent the valid or expected arguments to a mocked method.
|
// It is used to represent the valid or expected arguments to a mocked method.
|
||||||
type Matcher interface {
|
type Matcher interface {
|
||||||
// Matches returns whether y is a match.
|
// Matches returns whether x is a match.
|
||||||
Matches(x interface{}) bool
|
Matches(x interface{}) bool
|
||||||
|
|
||||||
// String describes what the matcher matches.
|
// String describes what the matcher matches.
|
||||||
|
|
|
@ -1,49 +1,57 @@
|
||||||
// Automatically generated by MockGen. DO NOT EDIT!
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/golang/mock/gomock (interfaces: Matcher)
|
// Source: github.com/golang/mock/gomock (interfaces: Matcher)
|
||||||
|
|
||||||
|
// Package mock_gomock is a generated GoMock package.
|
||||||
package mock_gomock
|
package mock_gomock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mock of Matcher interface
|
// MockMatcher is a mock of Matcher interface
|
||||||
type MockMatcher struct {
|
type MockMatcher struct {
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *_MockMatcherRecorder
|
recorder *MockMatcherMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recorder for MockMatcher (not exported)
|
// MockMatcherMockRecorder is the mock recorder for MockMatcher
|
||||||
type _MockMatcherRecorder struct {
|
type MockMatcherMockRecorder struct {
|
||||||
mock *MockMatcher
|
mock *MockMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMockMatcher creates a new mock instance
|
||||||
func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher {
|
func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher {
|
||||||
mock := &MockMatcher{ctrl: ctrl}
|
mock := &MockMatcher{ctrl: ctrl}
|
||||||
mock.recorder = &_MockMatcherRecorder{mock}
|
mock.recorder = &MockMatcherMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *MockMatcher) EXPECT() *_MockMatcherRecorder {
|
// EXPECT returns an object that allows the caller to indicate expected use
|
||||||
return _m.recorder
|
func (m *MockMatcher) EXPECT() *MockMatcherMockRecorder {
|
||||||
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *MockMatcher) Matches(_param0 interface{}) bool {
|
// Matches mocks base method
|
||||||
ret := _m.ctrl.Call(_m, "Matches", _param0)
|
func (m *MockMatcher) Matches(arg0 interface{}) bool {
|
||||||
|
ret := m.ctrl.Call(m, "Matches", arg0)
|
||||||
ret0, _ := ret[0].(bool)
|
ret0, _ := ret[0].(bool)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_mr *_MockMatcherRecorder) Matches(arg0 interface{}) *gomock.Call {
|
// Matches indicates an expected call of Matches
|
||||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Matches", arg0)
|
func (mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call {
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *MockMatcher) String() string {
|
// String mocks base method
|
||||||
ret := _m.ctrl.Call(_m, "String")
|
func (m *MockMatcher) String() string {
|
||||||
|
ret := m.ctrl.Call(m, "String")
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(string)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_mr *_MockMatcherRecorder) String() *gomock.Call {
|
// String indicates an expected call of String
|
||||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "String")
|
func (mr *MockMatcherMockRecorder) String() *gomock.Call {
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
install:
|
||||||
|
go install
|
||||||
|
|
||||||
|
test: install generate-test-pbs
|
||||||
|
go test
|
||||||
|
|
||||||
|
|
||||||
|
generate-test-pbs:
|
||||||
|
make install
|
||||||
|
make -C testdata
|
||||||
|
protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
|
||||||
|
make
|
|
@ -174,11 +174,11 @@ func sizeFixed32(x uint64) int {
|
||||||
// This is the format used for the sint64 protocol buffer type.
|
// This is the format used for the sint64 protocol buffer type.
|
||||||
func (p *Buffer) EncodeZigzag64(x uint64) error {
|
func (p *Buffer) EncodeZigzag64(x uint64) error {
|
||||||
// use signed number to get arithmetic right shift.
|
// use signed number to get arithmetic right shift.
|
||||||
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func sizeZigzag64(x uint64) int {
|
func sizeZigzag64(x uint64) int {
|
||||||
return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
|
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
|
||||||
|
|
|
@ -73,7 +73,6 @@ for a protocol buffer variable v:
|
||||||
When the .proto file specifies `syntax="proto3"`, there are some differences:
|
When the .proto file specifies `syntax="proto3"`, there are some differences:
|
||||||
|
|
||||||
- Non-repeated fields of non-message type are values instead of pointers.
|
- Non-repeated fields of non-message type are values instead of pointers.
|
||||||
- Getters are only generated for message and oneof fields.
|
|
||||||
- Enum types do not get an Enum method.
|
- Enum types do not get an Enum method.
|
||||||
|
|
||||||
The simplest way to describe this is to see an example.
|
The simplest way to describe this is to see an example.
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
//
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/any.proto";
|
||||||
|
import "testdata/test.proto";
|
||||||
|
|
||||||
|
package proto3_proto;
|
||||||
|
|
||||||
|
message Message {
|
||||||
|
enum Humour {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
PUNS = 1;
|
||||||
|
SLAPSTICK = 2;
|
||||||
|
BILL_BAILEY = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = 1;
|
||||||
|
Humour hilarity = 2;
|
||||||
|
uint32 height_in_cm = 3;
|
||||||
|
bytes data = 4;
|
||||||
|
int64 result_count = 7;
|
||||||
|
bool true_scotsman = 8;
|
||||||
|
float score = 9;
|
||||||
|
|
||||||
|
repeated uint64 key = 5;
|
||||||
|
repeated int32 short_key = 19;
|
||||||
|
Nested nested = 6;
|
||||||
|
repeated Humour r_funny = 16;
|
||||||
|
|
||||||
|
map<string, Nested> terrain = 10;
|
||||||
|
testdata.SubDefaults proto2_field = 11;
|
||||||
|
map<string, testdata.SubDefaults> proto2_value = 13;
|
||||||
|
|
||||||
|
google.protobuf.Any anything = 14;
|
||||||
|
repeated google.protobuf.Any many_things = 15;
|
||||||
|
|
||||||
|
Message submessage = 17;
|
||||||
|
repeated Message children = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Nested {
|
||||||
|
string bunny = 1;
|
||||||
|
bool cute = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageWithMap {
|
||||||
|
map<bool, bytes> byte_mapping = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message IntMap {
|
||||||
|
map<int32, int32> rtt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IntMaps {
|
||||||
|
repeated IntMap maps = 1;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
include ../../Make.protobuf
|
||||||
|
|
||||||
|
all: regenerate
|
||||||
|
|
||||||
|
regenerate:
|
||||||
|
rm -f test.pb.go
|
||||||
|
make test.pb.go
|
||||||
|
|
||||||
|
# The following rules are just aids to development. Not needed for typical testing.
|
||||||
|
|
||||||
|
diff: regenerate
|
||||||
|
git diff test.pb.go
|
||||||
|
|
||||||
|
restore:
|
||||||
|
cp test.pb.go.golden test.pb.go
|
||||||
|
|
||||||
|
preserve:
|
||||||
|
cp test.pb.go test.pb.go.golden
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,548 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// A feature-rich test file for the protocol compiler and libraries.
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
package testdata;
|
||||||
|
|
||||||
|
enum FOO { FOO1 = 1; };
|
||||||
|
|
||||||
|
message GoEnum {
|
||||||
|
required FOO foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GoTestField {
|
||||||
|
required string Label = 1;
|
||||||
|
required string Type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GoTest {
|
||||||
|
// An enum, for completeness.
|
||||||
|
enum KIND {
|
||||||
|
VOID = 0;
|
||||||
|
|
||||||
|
// Basic types
|
||||||
|
BOOL = 1;
|
||||||
|
BYTES = 2;
|
||||||
|
FINGERPRINT = 3;
|
||||||
|
FLOAT = 4;
|
||||||
|
INT = 5;
|
||||||
|
STRING = 6;
|
||||||
|
TIME = 7;
|
||||||
|
|
||||||
|
// Groupings
|
||||||
|
TUPLE = 8;
|
||||||
|
ARRAY = 9;
|
||||||
|
MAP = 10;
|
||||||
|
|
||||||
|
// Table types
|
||||||
|
TABLE = 11;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
FUNCTION = 12; // last tag
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some typical parameters
|
||||||
|
required KIND Kind = 1;
|
||||||
|
optional string Table = 2;
|
||||||
|
optional int32 Param = 3;
|
||||||
|
|
||||||
|
// Required, repeated and optional foreign fields.
|
||||||
|
required GoTestField RequiredField = 4;
|
||||||
|
repeated GoTestField RepeatedField = 5;
|
||||||
|
optional GoTestField OptionalField = 6;
|
||||||
|
|
||||||
|
// Required fields of all basic types
|
||||||
|
required bool F_Bool_required = 10;
|
||||||
|
required int32 F_Int32_required = 11;
|
||||||
|
required int64 F_Int64_required = 12;
|
||||||
|
required fixed32 F_Fixed32_required = 13;
|
||||||
|
required fixed64 F_Fixed64_required = 14;
|
||||||
|
required uint32 F_Uint32_required = 15;
|
||||||
|
required uint64 F_Uint64_required = 16;
|
||||||
|
required float F_Float_required = 17;
|
||||||
|
required double F_Double_required = 18;
|
||||||
|
required string F_String_required = 19;
|
||||||
|
required bytes F_Bytes_required = 101;
|
||||||
|
required sint32 F_Sint32_required = 102;
|
||||||
|
required sint64 F_Sint64_required = 103;
|
||||||
|
|
||||||
|
// Repeated fields of all basic types
|
||||||
|
repeated bool F_Bool_repeated = 20;
|
||||||
|
repeated int32 F_Int32_repeated = 21;
|
||||||
|
repeated int64 F_Int64_repeated = 22;
|
||||||
|
repeated fixed32 F_Fixed32_repeated = 23;
|
||||||
|
repeated fixed64 F_Fixed64_repeated = 24;
|
||||||
|
repeated uint32 F_Uint32_repeated = 25;
|
||||||
|
repeated uint64 F_Uint64_repeated = 26;
|
||||||
|
repeated float F_Float_repeated = 27;
|
||||||
|
repeated double F_Double_repeated = 28;
|
||||||
|
repeated string F_String_repeated = 29;
|
||||||
|
repeated bytes F_Bytes_repeated = 201;
|
||||||
|
repeated sint32 F_Sint32_repeated = 202;
|
||||||
|
repeated sint64 F_Sint64_repeated = 203;
|
||||||
|
|
||||||
|
// Optional fields of all basic types
|
||||||
|
optional bool F_Bool_optional = 30;
|
||||||
|
optional int32 F_Int32_optional = 31;
|
||||||
|
optional int64 F_Int64_optional = 32;
|
||||||
|
optional fixed32 F_Fixed32_optional = 33;
|
||||||
|
optional fixed64 F_Fixed64_optional = 34;
|
||||||
|
optional uint32 F_Uint32_optional = 35;
|
||||||
|
optional uint64 F_Uint64_optional = 36;
|
||||||
|
optional float F_Float_optional = 37;
|
||||||
|
optional double F_Double_optional = 38;
|
||||||
|
optional string F_String_optional = 39;
|
||||||
|
optional bytes F_Bytes_optional = 301;
|
||||||
|
optional sint32 F_Sint32_optional = 302;
|
||||||
|
optional sint64 F_Sint64_optional = 303;
|
||||||
|
|
||||||
|
// Default-valued fields of all basic types
|
||||||
|
optional bool F_Bool_defaulted = 40 [default=true];
|
||||||
|
optional int32 F_Int32_defaulted = 41 [default=32];
|
||||||
|
optional int64 F_Int64_defaulted = 42 [default=64];
|
||||||
|
optional fixed32 F_Fixed32_defaulted = 43 [default=320];
|
||||||
|
optional fixed64 F_Fixed64_defaulted = 44 [default=640];
|
||||||
|
optional uint32 F_Uint32_defaulted = 45 [default=3200];
|
||||||
|
optional uint64 F_Uint64_defaulted = 46 [default=6400];
|
||||||
|
optional float F_Float_defaulted = 47 [default=314159.];
|
||||||
|
optional double F_Double_defaulted = 48 [default=271828.];
|
||||||
|
optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
|
||||||
|
optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
|
||||||
|
optional sint32 F_Sint32_defaulted = 402 [default = -32];
|
||||||
|
optional sint64 F_Sint64_defaulted = 403 [default = -64];
|
||||||
|
|
||||||
|
// Packed repeated fields (no string or bytes).
|
||||||
|
repeated bool F_Bool_repeated_packed = 50 [packed=true];
|
||||||
|
repeated int32 F_Int32_repeated_packed = 51 [packed=true];
|
||||||
|
repeated int64 F_Int64_repeated_packed = 52 [packed=true];
|
||||||
|
repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
|
||||||
|
repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
|
||||||
|
repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
|
||||||
|
repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
|
||||||
|
repeated float F_Float_repeated_packed = 57 [packed=true];
|
||||||
|
repeated double F_Double_repeated_packed = 58 [packed=true];
|
||||||
|
repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
|
||||||
|
repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
|
||||||
|
|
||||||
|
// Required, repeated, and optional groups.
|
||||||
|
required group RequiredGroup = 70 {
|
||||||
|
required string RequiredField = 71;
|
||||||
|
};
|
||||||
|
|
||||||
|
repeated group RepeatedGroup = 80 {
|
||||||
|
required string RequiredField = 81;
|
||||||
|
};
|
||||||
|
|
||||||
|
optional group OptionalGroup = 90 {
|
||||||
|
required string RequiredField = 91;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing a group containing a required field.
|
||||||
|
message GoTestRequiredGroupField {
|
||||||
|
required group Group = 1 {
|
||||||
|
required int32 Field = 2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing skipping of unrecognized fields.
|
||||||
|
// Numbers are all big, larger than tag numbers in GoTestField,
|
||||||
|
// the message used in the corresponding test.
|
||||||
|
message GoSkipTest {
|
||||||
|
required int32 skip_int32 = 11;
|
||||||
|
required fixed32 skip_fixed32 = 12;
|
||||||
|
required fixed64 skip_fixed64 = 13;
|
||||||
|
required string skip_string = 14;
|
||||||
|
required group SkipGroup = 15 {
|
||||||
|
required int32 group_int32 = 16;
|
||||||
|
required string group_string = 17;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing packed/non-packed decoder switching.
|
||||||
|
// A serialized instance of one should be deserializable as the other.
|
||||||
|
message NonPackedTest {
|
||||||
|
repeated int32 a = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PackedTest {
|
||||||
|
repeated int32 b = 1 [packed=true];
|
||||||
|
}
|
||||||
|
|
||||||
|
message MaxTag {
|
||||||
|
// Maximum possible tag number.
|
||||||
|
optional string last_field = 536870911;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OldMessage {
|
||||||
|
message Nested {
|
||||||
|
optional string name = 1;
|
||||||
|
}
|
||||||
|
optional Nested nested = 1;
|
||||||
|
|
||||||
|
optional int32 num = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMessage is wire compatible with OldMessage;
|
||||||
|
// imagine it as a future version.
|
||||||
|
message NewMessage {
|
||||||
|
message Nested {
|
||||||
|
optional string name = 1;
|
||||||
|
optional string food_group = 2;
|
||||||
|
}
|
||||||
|
optional Nested nested = 1;
|
||||||
|
|
||||||
|
// This is an int32 in OldMessage.
|
||||||
|
optional int64 num = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smaller tests for ASCII formatting.
|
||||||
|
|
||||||
|
message InnerMessage {
|
||||||
|
required string host = 1;
|
||||||
|
optional int32 port = 2 [default=4000];
|
||||||
|
optional bool connected = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OtherMessage {
|
||||||
|
optional int64 key = 1;
|
||||||
|
optional bytes value = 2;
|
||||||
|
optional float weight = 3;
|
||||||
|
optional InnerMessage inner = 4;
|
||||||
|
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RequiredInnerMessage {
|
||||||
|
required InnerMessage leo_finally_won_an_oscar = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MyMessage {
|
||||||
|
required int32 count = 1;
|
||||||
|
optional string name = 2;
|
||||||
|
optional string quote = 3;
|
||||||
|
repeated string pet = 4;
|
||||||
|
optional InnerMessage inner = 5;
|
||||||
|
repeated OtherMessage others = 6;
|
||||||
|
optional RequiredInnerMessage we_must_go_deeper = 13;
|
||||||
|
repeated InnerMessage rep_inner = 12;
|
||||||
|
|
||||||
|
enum Color {
|
||||||
|
RED = 0;
|
||||||
|
GREEN = 1;
|
||||||
|
BLUE = 2;
|
||||||
|
};
|
||||||
|
optional Color bikeshed = 7;
|
||||||
|
|
||||||
|
optional group SomeGroup = 8 {
|
||||||
|
optional int32 group_field = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This field becomes [][]byte in the generated code.
|
||||||
|
repeated bytes rep_bytes = 10;
|
||||||
|
|
||||||
|
optional double bigfloat = 11;
|
||||||
|
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Ext {
|
||||||
|
extend MyMessage {
|
||||||
|
optional Ext more = 103;
|
||||||
|
optional string text = 104;
|
||||||
|
optional int32 number = 105;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional string data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend MyMessage {
|
||||||
|
repeated string greeting = 106;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComplexExtension {
|
||||||
|
optional int32 first = 1;
|
||||||
|
optional int32 second = 2;
|
||||||
|
repeated int32 third = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend OtherMessage {
|
||||||
|
optional ComplexExtension complex = 200;
|
||||||
|
repeated ComplexExtension r_complex = 201;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DefaultsMessage {
|
||||||
|
enum DefaultsEnum {
|
||||||
|
ZERO = 0;
|
||||||
|
ONE = 1;
|
||||||
|
TWO = 2;
|
||||||
|
};
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend DefaultsMessage {
|
||||||
|
optional double no_default_double = 101;
|
||||||
|
optional float no_default_float = 102;
|
||||||
|
optional int32 no_default_int32 = 103;
|
||||||
|
optional int64 no_default_int64 = 104;
|
||||||
|
optional uint32 no_default_uint32 = 105;
|
||||||
|
optional uint64 no_default_uint64 = 106;
|
||||||
|
optional sint32 no_default_sint32 = 107;
|
||||||
|
optional sint64 no_default_sint64 = 108;
|
||||||
|
optional fixed32 no_default_fixed32 = 109;
|
||||||
|
optional fixed64 no_default_fixed64 = 110;
|
||||||
|
optional sfixed32 no_default_sfixed32 = 111;
|
||||||
|
optional sfixed64 no_default_sfixed64 = 112;
|
||||||
|
optional bool no_default_bool = 113;
|
||||||
|
optional string no_default_string = 114;
|
||||||
|
optional bytes no_default_bytes = 115;
|
||||||
|
optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
|
||||||
|
|
||||||
|
optional double default_double = 201 [default = 3.1415];
|
||||||
|
optional float default_float = 202 [default = 3.14];
|
||||||
|
optional int32 default_int32 = 203 [default = 42];
|
||||||
|
optional int64 default_int64 = 204 [default = 43];
|
||||||
|
optional uint32 default_uint32 = 205 [default = 44];
|
||||||
|
optional uint64 default_uint64 = 206 [default = 45];
|
||||||
|
optional sint32 default_sint32 = 207 [default = 46];
|
||||||
|
optional sint64 default_sint64 = 208 [default = 47];
|
||||||
|
optional fixed32 default_fixed32 = 209 [default = 48];
|
||||||
|
optional fixed64 default_fixed64 = 210 [default = 49];
|
||||||
|
optional sfixed32 default_sfixed32 = 211 [default = 50];
|
||||||
|
optional sfixed64 default_sfixed64 = 212 [default = 51];
|
||||||
|
optional bool default_bool = 213 [default = true];
|
||||||
|
optional string default_string = 214 [default = "Hello, string"];
|
||||||
|
optional bytes default_bytes = 215 [default = "Hello, bytes"];
|
||||||
|
optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
|
||||||
|
}
|
||||||
|
|
||||||
|
message MyMessageSet {
|
||||||
|
option message_set_wire_format = true;
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Empty {
|
||||||
|
}
|
||||||
|
|
||||||
|
extend MyMessageSet {
|
||||||
|
optional Empty x201 = 201;
|
||||||
|
optional Empty x202 = 202;
|
||||||
|
optional Empty x203 = 203;
|
||||||
|
optional Empty x204 = 204;
|
||||||
|
optional Empty x205 = 205;
|
||||||
|
optional Empty x206 = 206;
|
||||||
|
optional Empty x207 = 207;
|
||||||
|
optional Empty x208 = 208;
|
||||||
|
optional Empty x209 = 209;
|
||||||
|
optional Empty x210 = 210;
|
||||||
|
optional Empty x211 = 211;
|
||||||
|
optional Empty x212 = 212;
|
||||||
|
optional Empty x213 = 213;
|
||||||
|
optional Empty x214 = 214;
|
||||||
|
optional Empty x215 = 215;
|
||||||
|
optional Empty x216 = 216;
|
||||||
|
optional Empty x217 = 217;
|
||||||
|
optional Empty x218 = 218;
|
||||||
|
optional Empty x219 = 219;
|
||||||
|
optional Empty x220 = 220;
|
||||||
|
optional Empty x221 = 221;
|
||||||
|
optional Empty x222 = 222;
|
||||||
|
optional Empty x223 = 223;
|
||||||
|
optional Empty x224 = 224;
|
||||||
|
optional Empty x225 = 225;
|
||||||
|
optional Empty x226 = 226;
|
||||||
|
optional Empty x227 = 227;
|
||||||
|
optional Empty x228 = 228;
|
||||||
|
optional Empty x229 = 229;
|
||||||
|
optional Empty x230 = 230;
|
||||||
|
optional Empty x231 = 231;
|
||||||
|
optional Empty x232 = 232;
|
||||||
|
optional Empty x233 = 233;
|
||||||
|
optional Empty x234 = 234;
|
||||||
|
optional Empty x235 = 235;
|
||||||
|
optional Empty x236 = 236;
|
||||||
|
optional Empty x237 = 237;
|
||||||
|
optional Empty x238 = 238;
|
||||||
|
optional Empty x239 = 239;
|
||||||
|
optional Empty x240 = 240;
|
||||||
|
optional Empty x241 = 241;
|
||||||
|
optional Empty x242 = 242;
|
||||||
|
optional Empty x243 = 243;
|
||||||
|
optional Empty x244 = 244;
|
||||||
|
optional Empty x245 = 245;
|
||||||
|
optional Empty x246 = 246;
|
||||||
|
optional Empty x247 = 247;
|
||||||
|
optional Empty x248 = 248;
|
||||||
|
optional Empty x249 = 249;
|
||||||
|
optional Empty x250 = 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageList {
|
||||||
|
repeated group Message = 1 {
|
||||||
|
required string name = 2;
|
||||||
|
required int32 count = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Strings {
|
||||||
|
optional string string_field = 1;
|
||||||
|
optional bytes bytes_field = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Defaults {
|
||||||
|
enum Color {
|
||||||
|
RED = 0;
|
||||||
|
GREEN = 1;
|
||||||
|
BLUE = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default-valued fields of all basic types.
|
||||||
|
// Same as GoTest, but copied here to make testing easier.
|
||||||
|
optional bool F_Bool = 1 [default=true];
|
||||||
|
optional int32 F_Int32 = 2 [default=32];
|
||||||
|
optional int64 F_Int64 = 3 [default=64];
|
||||||
|
optional fixed32 F_Fixed32 = 4 [default=320];
|
||||||
|
optional fixed64 F_Fixed64 = 5 [default=640];
|
||||||
|
optional uint32 F_Uint32 = 6 [default=3200];
|
||||||
|
optional uint64 F_Uint64 = 7 [default=6400];
|
||||||
|
optional float F_Float = 8 [default=314159.];
|
||||||
|
optional double F_Double = 9 [default=271828.];
|
||||||
|
optional string F_String = 10 [default="hello, \"world!\"\n"];
|
||||||
|
optional bytes F_Bytes = 11 [default="Bignose"];
|
||||||
|
optional sint32 F_Sint32 = 12 [default=-32];
|
||||||
|
optional sint64 F_Sint64 = 13 [default=-64];
|
||||||
|
optional Color F_Enum = 14 [default=GREEN];
|
||||||
|
|
||||||
|
// More fields with crazy defaults.
|
||||||
|
optional float F_Pinf = 15 [default=inf];
|
||||||
|
optional float F_Ninf = 16 [default=-inf];
|
||||||
|
optional float F_Nan = 17 [default=nan];
|
||||||
|
|
||||||
|
// Sub-message.
|
||||||
|
optional SubDefaults sub = 18;
|
||||||
|
|
||||||
|
// Redundant but explicit defaults.
|
||||||
|
optional string str_zero = 19 [default=""];
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubDefaults {
|
||||||
|
optional int64 n = 1 [default=7];
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepeatedEnum {
|
||||||
|
enum Color {
|
||||||
|
RED = 1;
|
||||||
|
}
|
||||||
|
repeated Color color = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MoreRepeated {
|
||||||
|
repeated bool bools = 1;
|
||||||
|
repeated bool bools_packed = 2 [packed=true];
|
||||||
|
repeated int32 ints = 3;
|
||||||
|
repeated int32 ints_packed = 4 [packed=true];
|
||||||
|
repeated int64 int64s_packed = 7 [packed=true];
|
||||||
|
repeated string strings = 5;
|
||||||
|
repeated fixed32 fixeds = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupOld and GroupNew have the same wire format.
|
||||||
|
// GroupNew has a new field inside a group.
|
||||||
|
|
||||||
|
message GroupOld {
|
||||||
|
optional group G = 101 {
|
||||||
|
optional int32 x = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupNew {
|
||||||
|
optional group G = 101 {
|
||||||
|
optional int32 x = 2;
|
||||||
|
optional int32 y = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message FloatingPoint {
|
||||||
|
required double f = 1;
|
||||||
|
optional bool exact = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageWithMap {
|
||||||
|
map<int32, string> name_mapping = 1;
|
||||||
|
map<sint64, FloatingPoint> msg_mapping = 2;
|
||||||
|
map<bool, bytes> byte_mapping = 3;
|
||||||
|
map<string, string> str_to_str = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Oneof {
|
||||||
|
oneof union {
|
||||||
|
bool F_Bool = 1;
|
||||||
|
int32 F_Int32 = 2;
|
||||||
|
int64 F_Int64 = 3;
|
||||||
|
fixed32 F_Fixed32 = 4;
|
||||||
|
fixed64 F_Fixed64 = 5;
|
||||||
|
uint32 F_Uint32 = 6;
|
||||||
|
uint64 F_Uint64 = 7;
|
||||||
|
float F_Float = 8;
|
||||||
|
double F_Double = 9;
|
||||||
|
string F_String = 10;
|
||||||
|
bytes F_Bytes = 11;
|
||||||
|
sint32 F_Sint32 = 12;
|
||||||
|
sint64 F_Sint64 = 13;
|
||||||
|
MyMessage.Color F_Enum = 14;
|
||||||
|
GoTestField F_Message = 15;
|
||||||
|
group F_Group = 16 {
|
||||||
|
optional int32 x = 17;
|
||||||
|
}
|
||||||
|
int32 F_Largest_Tag = 536870911;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof tormato {
|
||||||
|
int32 value = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Communique {
|
||||||
|
optional bool make_me_cry = 1;
|
||||||
|
|
||||||
|
// This is a oneof, called "union".
|
||||||
|
oneof union {
|
||||||
|
int32 number = 5;
|
||||||
|
string name = 6;
|
||||||
|
bytes data = 7;
|
||||||
|
double temp_c = 8;
|
||||||
|
MyMessage.Color col = 9;
|
||||||
|
Strings msg = 10;
|
||||||
|
}
|
||||||
|
}
|
|
@ -865,7 +865,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
||||||
return p.readStruct(fv, terminator)
|
return p.readStruct(fv, terminator)
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||||
fv.SetUint(uint64(x))
|
fv.SetUint(x)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
|
|
|
@ -1,31 +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.
|
|
||||||
|
|
37
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
generated
vendored
Normal file
37
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/
|
||||||
|
# at src/google/protobuf/descriptor.proto
|
||||||
|
regenerate:
|
||||||
|
@echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
|
||||||
|
cp $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto .
|
||||||
|
protoc --go_out=../../../../.. -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto
|
|
@ -1,6 +1,5 @@
|
||||||
// Code generated by protoc-gen-go.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: google/protobuf/descriptor.proto
|
// source: google/protobuf/descriptor.proto
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package descriptor is a generated protocol buffer package.
|
Package descriptor is a generated protocol buffer package.
|
||||||
|
@ -12,6 +11,7 @@ It has these top-level messages:
|
||||||
FileDescriptorSet
|
FileDescriptorSet
|
||||||
FileDescriptorProto
|
FileDescriptorProto
|
||||||
DescriptorProto
|
DescriptorProto
|
||||||
|
ExtensionRangeOptions
|
||||||
FieldDescriptorProto
|
FieldDescriptorProto
|
||||||
OneofDescriptorProto
|
OneofDescriptorProto
|
||||||
EnumDescriptorProto
|
EnumDescriptorProto
|
||||||
|
@ -65,6 +65,10 @@ const (
|
||||||
FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7
|
FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7
|
||||||
FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8
|
FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8
|
||||||
FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9
|
FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9
|
||||||
|
// Tag-delimited aggregate.
|
||||||
|
// Group type is deprecated and not supported in proto3. However, Proto3
|
||||||
|
// implementations should still be able to parse the group wire format and
|
||||||
|
// treat group fields as unknown fields.
|
||||||
FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
|
FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
|
||||||
FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11
|
FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11
|
||||||
// New in version 2.
|
// New in version 2.
|
||||||
|
@ -134,7 +138,7 @@ func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error {
|
||||||
*x = FieldDescriptorProto_Type(value)
|
*x = FieldDescriptorProto_Type(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} }
|
func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} }
|
||||||
|
|
||||||
type FieldDescriptorProto_Label int32
|
type FieldDescriptorProto_Label int32
|
||||||
|
|
||||||
|
@ -173,7 +177,7 @@ func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
|
func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{3, 1}
|
return fileDescriptor0, []int{4, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generated classes can be optimized for speed or code size.
|
// Generated classes can be optimized for speed or code size.
|
||||||
|
@ -213,7 +217,7 @@ func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error {
|
||||||
*x = FileOptions_OptimizeMode(value)
|
*x = FileOptions_OptimizeMode(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} }
|
func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} }
|
||||||
|
|
||||||
type FieldOptions_CType int32
|
type FieldOptions_CType int32
|
||||||
|
|
||||||
|
@ -251,7 +255,7 @@ func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error {
|
||||||
*x = FieldOptions_CType(value)
|
*x = FieldOptions_CType(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} }
|
func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} }
|
||||||
|
|
||||||
type FieldOptions_JSType int32
|
type FieldOptions_JSType int32
|
||||||
|
|
||||||
|
@ -291,7 +295,49 @@ func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error {
|
||||||
*x = FieldOptions_JSType(value)
|
*x = FieldOptions_JSType(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 1} }
|
func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 1} }
|
||||||
|
|
||||||
|
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
|
||||||
|
// or neither? HTTP based RPC implementation may choose GET verb for safe
|
||||||
|
// methods, and PUT verb for idempotent methods instead of the default POST.
|
||||||
|
type MethodOptions_IdempotencyLevel int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0
|
||||||
|
MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1
|
||||||
|
MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var MethodOptions_IdempotencyLevel_name = map[int32]string{
|
||||||
|
0: "IDEMPOTENCY_UNKNOWN",
|
||||||
|
1: "NO_SIDE_EFFECTS",
|
||||||
|
2: "IDEMPOTENT",
|
||||||
|
}
|
||||||
|
var MethodOptions_IdempotencyLevel_value = map[string]int32{
|
||||||
|
"IDEMPOTENCY_UNKNOWN": 0,
|
||||||
|
"NO_SIDE_EFFECTS": 1,
|
||||||
|
"IDEMPOTENT": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel {
|
||||||
|
p := new(MethodOptions_IdempotencyLevel)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
func (x MethodOptions_IdempotencyLevel) String() string {
|
||||||
|
return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x))
|
||||||
|
}
|
||||||
|
func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error {
|
||||||
|
value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*x = MethodOptions_IdempotencyLevel(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor0, []int{17, 0}
|
||||||
|
}
|
||||||
|
|
||||||
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
||||||
// files it parses.
|
// files it parses.
|
||||||
|
@ -524,6 +570,7 @@ func (m *DescriptorProto) GetReservedName() []string {
|
||||||
type DescriptorProto_ExtensionRange struct {
|
type DescriptorProto_ExtensionRange struct {
|
||||||
Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
|
Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
|
||||||
End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
|
End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
|
||||||
|
Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,6 +595,13 @@ func (m *DescriptorProto_ExtensionRange) GetEnd() int32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions {
|
||||||
|
if m != nil {
|
||||||
|
return m.Options
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
||||||
// fields or extension ranges in the same message. Reserved ranges may
|
// fields or extension ranges in the same message. Reserved ranges may
|
||||||
// not overlap.
|
// not overlap.
|
||||||
|
@ -578,6 +632,33 @@ func (m *DescriptorProto_ReservedRange) GetEnd() int32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtensionRangeOptions struct {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} }
|
||||||
|
func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ExtensionRangeOptions) ProtoMessage() {}
|
||||||
|
func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||||
|
|
||||||
|
var extRange_ExtensionRangeOptions = []proto.ExtensionRange{
|
||||||
|
{1000, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_ExtensionRangeOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
|
if m != nil {
|
||||||
|
return m.UninterpretedOption
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Describes a field within a message.
|
// Describes a field within a message.
|
||||||
type FieldDescriptorProto struct {
|
type FieldDescriptorProto struct {
|
||||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||||
|
@ -616,7 +697,7 @@ type FieldDescriptorProto struct {
|
||||||
func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
|
func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
|
||||||
func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FieldDescriptorProto) ProtoMessage() {}
|
func (*FieldDescriptorProto) ProtoMessage() {}
|
||||||
func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||||
|
|
||||||
func (m *FieldDescriptorProto) GetName() string {
|
func (m *FieldDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
|
@ -698,7 +779,7 @@ type OneofDescriptorProto struct {
|
||||||
func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
|
func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
|
||||||
func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OneofDescriptorProto) ProtoMessage() {}
|
func (*OneofDescriptorProto) ProtoMessage() {}
|
||||||
func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||||
|
|
||||||
func (m *OneofDescriptorProto) GetName() string {
|
func (m *OneofDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
|
@ -725,7 +806,7 @@ type EnumDescriptorProto struct {
|
||||||
func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
|
func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
|
||||||
func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumDescriptorProto) ProtoMessage() {}
|
func (*EnumDescriptorProto) ProtoMessage() {}
|
||||||
func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||||
|
|
||||||
func (m *EnumDescriptorProto) GetName() string {
|
func (m *EnumDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
|
@ -759,7 +840,7 @@ type EnumValueDescriptorProto struct {
|
||||||
func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
|
func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
|
||||||
func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumValueDescriptorProto) ProtoMessage() {}
|
func (*EnumValueDescriptorProto) ProtoMessage() {}
|
||||||
func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||||
|
|
||||||
func (m *EnumValueDescriptorProto) GetName() string {
|
func (m *EnumValueDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
|
@ -793,7 +874,7 @@ type ServiceDescriptorProto struct {
|
||||||
func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
|
func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
|
||||||
func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ServiceDescriptorProto) ProtoMessage() {}
|
func (*ServiceDescriptorProto) ProtoMessage() {}
|
||||||
func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||||
|
|
||||||
func (m *ServiceDescriptorProto) GetName() string {
|
func (m *ServiceDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
|
@ -834,7 +915,7 @@ type MethodDescriptorProto struct {
|
||||||
func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
|
func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
|
||||||
func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MethodDescriptorProto) ProtoMessage() {}
|
func (*MethodDescriptorProto) ProtoMessage() {}
|
||||||
func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
||||||
|
|
||||||
const Default_MethodDescriptorProto_ClientStreaming bool = false
|
const Default_MethodDescriptorProto_ClientStreaming bool = false
|
||||||
const Default_MethodDescriptorProto_ServerStreaming bool = false
|
const Default_MethodDescriptorProto_ServerStreaming bool = false
|
||||||
|
@ -929,6 +1010,7 @@ type FileOptions struct {
|
||||||
CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
|
CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
|
||||||
JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
|
JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
|
||||||
PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
|
PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
|
||||||
|
PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
|
||||||
// Is this file deprecated?
|
// Is this file deprecated?
|
||||||
// Depending on the target platform, this can emit Deprecated annotations
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
// for everything in the file, or it will be completely ignored; in the very
|
// for everything in the file, or it will be completely ignored; in the very
|
||||||
|
@ -942,6 +1024,18 @@ type FileOptions struct {
|
||||||
ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"`
|
ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"`
|
||||||
// Namespace for generated classes; defaults to the package.
|
// Namespace for generated classes; defaults to the package.
|
||||||
CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
|
CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
|
||||||
|
// By default Swift generators will take the proto package and CamelCase it
|
||||||
|
// replacing '.' with underscore and use that to prefix the types/symbols
|
||||||
|
// defined. When this options is provided, they will use this value instead
|
||||||
|
// to prefix the types/symbols defined.
|
||||||
|
SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"`
|
||||||
|
// Sets the php class prefix which is prepended to all php generated classes
|
||||||
|
// from this .proto. Default is empty.
|
||||||
|
PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"`
|
||||||
|
// Use this option to change the namespace of php generated classes. Default
|
||||||
|
// is empty. When this option is empty, the package name will be used for
|
||||||
|
// determining the namespace.
|
||||||
|
PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"`
|
||||||
// The parser stores options it doesn't recognize here. See above.
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
||||||
proto.XXX_InternalExtensions `json:"-"`
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
@ -951,7 +1045,7 @@ type FileOptions struct {
|
||||||
func (m *FileOptions) Reset() { *m = FileOptions{} }
|
func (m *FileOptions) Reset() { *m = FileOptions{} }
|
||||||
func (m *FileOptions) String() string { return proto.CompactTextString(m) }
|
func (m *FileOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FileOptions) ProtoMessage() {}
|
func (*FileOptions) ProtoMessage() {}
|
||||||
func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
||||||
|
|
||||||
var extRange_FileOptions = []proto.ExtensionRange{
|
var extRange_FileOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -967,6 +1061,7 @@ const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPE
|
||||||
const Default_FileOptions_CcGenericServices bool = false
|
const Default_FileOptions_CcGenericServices bool = false
|
||||||
const Default_FileOptions_JavaGenericServices bool = false
|
const Default_FileOptions_JavaGenericServices bool = false
|
||||||
const Default_FileOptions_PyGenericServices bool = false
|
const Default_FileOptions_PyGenericServices bool = false
|
||||||
|
const Default_FileOptions_PhpGenericServices bool = false
|
||||||
const Default_FileOptions_Deprecated bool = false
|
const Default_FileOptions_Deprecated bool = false
|
||||||
const Default_FileOptions_CcEnableArenas bool = false
|
const Default_FileOptions_CcEnableArenas bool = false
|
||||||
|
|
||||||
|
@ -1040,6 +1135,13 @@ func (m *FileOptions) GetPyGenericServices() bool {
|
||||||
return Default_FileOptions_PyGenericServices
|
return Default_FileOptions_PyGenericServices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *FileOptions) GetPhpGenericServices() bool {
|
||||||
|
if m != nil && m.PhpGenericServices != nil {
|
||||||
|
return *m.PhpGenericServices
|
||||||
|
}
|
||||||
|
return Default_FileOptions_PhpGenericServices
|
||||||
|
}
|
||||||
|
|
||||||
func (m *FileOptions) GetDeprecated() bool {
|
func (m *FileOptions) GetDeprecated() bool {
|
||||||
if m != nil && m.Deprecated != nil {
|
if m != nil && m.Deprecated != nil {
|
||||||
return *m.Deprecated
|
return *m.Deprecated
|
||||||
|
@ -1068,6 +1170,27 @@ func (m *FileOptions) GetCsharpNamespace() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *FileOptions) GetSwiftPrefix() string {
|
||||||
|
if m != nil && m.SwiftPrefix != nil {
|
||||||
|
return *m.SwiftPrefix
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileOptions) GetPhpClassPrefix() string {
|
||||||
|
if m != nil && m.PhpClassPrefix != nil {
|
||||||
|
return *m.PhpClassPrefix
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileOptions) GetPhpNamespace() string {
|
||||||
|
if m != nil && m.PhpNamespace != nil {
|
||||||
|
return *m.PhpNamespace
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
|
func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.UninterpretedOption
|
return m.UninterpretedOption
|
||||||
|
@ -1135,7 +1258,7 @@ type MessageOptions struct {
|
||||||
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
|
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
|
||||||
func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
|
func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MessageOptions) ProtoMessage() {}
|
func (*MessageOptions) ProtoMessage() {}
|
||||||
func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
||||||
|
|
||||||
var extRange_MessageOptions = []proto.ExtensionRange{
|
var extRange_MessageOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1198,13 +1321,15 @@ type FieldOptions struct {
|
||||||
Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
|
Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
|
||||||
// The jstype option determines the JavaScript type used for values of the
|
// The jstype option determines the JavaScript type used for values of the
|
||||||
// field. The option is permitted only for 64 bit integral and fixed types
|
// field. The option is permitted only for 64 bit integral and fixed types
|
||||||
// (int64, uint64, sint64, fixed64, sfixed64). By default these types are
|
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
|
||||||
// represented as JavaScript strings. This avoids loss of precision that can
|
// is represented as JavaScript string, which avoids loss of precision that
|
||||||
// happen when a large value is converted to a floating point JavaScript
|
// can happen when a large value is converted to a floating point JavaScript.
|
||||||
// numbers. Specifying JS_NUMBER for the jstype causes the generated
|
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
|
||||||
// JavaScript code to use the JavaScript "number" type instead of strings.
|
// use the JavaScript "number" type. The behavior of the default option
|
||||||
// This option is an enum to permit additional types to be added,
|
// JS_NORMAL is implementation dependent.
|
||||||
// e.g. goog.math.Integer.
|
//
|
||||||
|
// This option is an enum to permit additional types to be added, e.g.
|
||||||
|
// goog.math.Integer.
|
||||||
Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
|
Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
|
||||||
// Should this field be parsed lazily? Lazy applies only to message-type
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
// fields. It means that when the outer message is initially parsed, the
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
|
@ -1251,7 +1376,7 @@ type FieldOptions struct {
|
||||||
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
|
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
|
||||||
func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
|
func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FieldOptions) ProtoMessage() {}
|
func (*FieldOptions) ProtoMessage() {}
|
||||||
func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
||||||
|
|
||||||
var extRange_FieldOptions = []proto.ExtensionRange{
|
var extRange_FieldOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1326,7 +1451,7 @@ type OneofOptions struct {
|
||||||
func (m *OneofOptions) Reset() { *m = OneofOptions{} }
|
func (m *OneofOptions) Reset() { *m = OneofOptions{} }
|
||||||
func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
|
func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OneofOptions) ProtoMessage() {}
|
func (*OneofOptions) ProtoMessage() {}
|
||||||
func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
||||||
|
|
||||||
var extRange_OneofOptions = []proto.ExtensionRange{
|
var extRange_OneofOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1361,7 +1486,7 @@ type EnumOptions struct {
|
||||||
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
|
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
|
||||||
func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
|
func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumOptions) ProtoMessage() {}
|
func (*EnumOptions) ProtoMessage() {}
|
||||||
func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
||||||
|
|
||||||
var extRange_EnumOptions = []proto.ExtensionRange{
|
var extRange_EnumOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1409,7 +1534,7 @@ type EnumValueOptions struct {
|
||||||
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
|
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
|
||||||
func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
|
func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumValueOptions) ProtoMessage() {}
|
func (*EnumValueOptions) ProtoMessage() {}
|
||||||
func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
|
||||||
|
|
||||||
var extRange_EnumValueOptions = []proto.ExtensionRange{
|
var extRange_EnumValueOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1450,7 +1575,7 @@ type ServiceOptions struct {
|
||||||
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
|
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
|
||||||
func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
|
func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ServiceOptions) ProtoMessage() {}
|
func (*ServiceOptions) ProtoMessage() {}
|
||||||
func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
|
func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
|
||||||
|
|
||||||
var extRange_ServiceOptions = []proto.ExtensionRange{
|
var extRange_ServiceOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1482,6 +1607,7 @@ type MethodOptions struct {
|
||||||
// for the method, or it will be completely ignored; in the very least,
|
// for the method, or it will be completely ignored; in the very least,
|
||||||
// this is a formalization for deprecating methods.
|
// this is a formalization for deprecating methods.
|
||||||
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
|
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
|
||||||
|
IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"`
|
||||||
// The parser stores options it doesn't recognize here. See above.
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
||||||
proto.XXX_InternalExtensions `json:"-"`
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
@ -1491,7 +1617,7 @@ type MethodOptions struct {
|
||||||
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
|
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
|
||||||
func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
|
func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MethodOptions) ProtoMessage() {}
|
func (*MethodOptions) ProtoMessage() {}
|
||||||
func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
|
func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
|
||||||
|
|
||||||
var extRange_MethodOptions = []proto.ExtensionRange{
|
var extRange_MethodOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
|
@ -1502,6 +1628,7 @@ func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Default_MethodOptions_Deprecated bool = false
|
const Default_MethodOptions_Deprecated bool = false
|
||||||
|
const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN
|
||||||
|
|
||||||
func (m *MethodOptions) GetDeprecated() bool {
|
func (m *MethodOptions) GetDeprecated() bool {
|
||||||
if m != nil && m.Deprecated != nil {
|
if m != nil && m.Deprecated != nil {
|
||||||
|
@ -1510,6 +1637,13 @@ func (m *MethodOptions) GetDeprecated() bool {
|
||||||
return Default_MethodOptions_Deprecated
|
return Default_MethodOptions_Deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel {
|
||||||
|
if m != nil && m.IdempotencyLevel != nil {
|
||||||
|
return *m.IdempotencyLevel
|
||||||
|
}
|
||||||
|
return Default_MethodOptions_IdempotencyLevel
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
|
func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.UninterpretedOption
|
return m.UninterpretedOption
|
||||||
|
@ -1539,7 +1673,7 @@ type UninterpretedOption struct {
|
||||||
func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
|
func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
|
||||||
func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
|
func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UninterpretedOption) ProtoMessage() {}
|
func (*UninterpretedOption) ProtoMessage() {}
|
||||||
func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
|
func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
|
||||||
|
|
||||||
func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
|
func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -1605,7 +1739,7 @@ func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOptio
|
||||||
func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
|
func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UninterpretedOption_NamePart) ProtoMessage() {}
|
func (*UninterpretedOption_NamePart) ProtoMessage() {}
|
||||||
func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
|
func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{17, 0}
|
return fileDescriptor0, []int{18, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UninterpretedOption_NamePart) GetNamePart() string {
|
func (m *UninterpretedOption_NamePart) GetNamePart() string {
|
||||||
|
@ -1675,7 +1809,7 @@ type SourceCodeInfo struct {
|
||||||
func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
|
func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
|
||||||
func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
|
func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SourceCodeInfo) ProtoMessage() {}
|
func (*SourceCodeInfo) ProtoMessage() {}
|
||||||
func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
|
func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
|
||||||
|
|
||||||
func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
|
func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -1771,7 +1905,7 @@ type SourceCodeInfo_Location struct {
|
||||||
func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
|
func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
|
||||||
func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
|
func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SourceCodeInfo_Location) ProtoMessage() {}
|
func (*SourceCodeInfo_Location) ProtoMessage() {}
|
||||||
func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18, 0} }
|
func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} }
|
||||||
|
|
||||||
func (m *SourceCodeInfo_Location) GetPath() []int32 {
|
func (m *SourceCodeInfo_Location) GetPath() []int32 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -1821,7 +1955,7 @@ type GeneratedCodeInfo struct {
|
||||||
func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
|
func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
|
||||||
func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
|
func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GeneratedCodeInfo) ProtoMessage() {}
|
func (*GeneratedCodeInfo) ProtoMessage() {}
|
||||||
func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
|
func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
|
||||||
|
|
||||||
func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
|
func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -1850,7 +1984,7 @@ func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_
|
||||||
func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
|
func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
|
func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
|
||||||
func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
|
func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{19, 0}
|
return fileDescriptor0, []int{20, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
|
func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
|
||||||
|
@ -1887,6 +2021,7 @@ func init() {
|
||||||
proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
|
proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
|
||||||
proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
|
proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
|
||||||
proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
|
proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
|
||||||
|
proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions")
|
||||||
proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
|
proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
|
||||||
proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
|
proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
|
||||||
proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
|
proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
|
||||||
|
@ -1912,154 +2047,169 @@ func init() {
|
||||||
proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
|
proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
|
||||||
proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
|
proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
|
||||||
proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
|
proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
|
||||||
|
proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 2295 bytes of a gzipped FileDescriptorProto
|
// 2519 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x59, 0x4f, 0x6f, 0x1b, 0xc7,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7,
|
||||||
0x15, 0xcf, 0xf2, 0x9f, 0xc8, 0x47, 0x8a, 0x1a, 0x8d, 0x14, 0x67, 0xad, 0xfc, 0xb1, 0xcc, 0xd8,
|
0x15, 0x0e, 0x7f, 0x45, 0x1e, 0x52, 0xd4, 0x68, 0xa4, 0xd8, 0x6b, 0xe5, 0xc7, 0x32, 0xf3, 0x63,
|
||||||
0xb1, 0x6c, 0xb7, 0x74, 0x20, 0xff, 0x89, 0xa3, 0x14, 0x29, 0x28, 0x71, 0xad, 0xd0, 0x90, 0x44,
|
0xd9, 0x69, 0xa8, 0x40, 0xb1, 0x1d, 0x47, 0x29, 0xd2, 0x52, 0xe4, 0x5a, 0xa1, 0x4a, 0x91, 0xec,
|
||||||
0x76, 0x29, 0xb5, 0x4e, 0x2e, 0x8b, 0xd1, 0xee, 0x90, 0x5a, 0x7b, 0x39, 0xbb, 0xdd, 0x5d, 0xda,
|
0x92, 0x6a, 0x7e, 0x6e, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, 0xb4, 0xad,
|
||||||
0x56, 0x4e, 0x06, 0x7a, 0xea, 0xa5, 0xe7, 0xa2, 0x2d, 0x7a, 0xc8, 0x25, 0x40, 0x3f, 0x40, 0x0f,
|
0xa0, 0x17, 0x06, 0x7a, 0x55, 0xa0, 0x0f, 0x50, 0x14, 0x45, 0x2f, 0x72, 0x13, 0xa0, 0x0f, 0x50,
|
||||||
0xfd, 0x0a, 0x05, 0x0a, 0xf4, 0x2b, 0x14, 0x05, 0xda, 0x6f, 0xd0, 0x6b, 0x31, 0x33, 0xbb, 0xcb,
|
0x20, 0x77, 0x7d, 0x82, 0x02, 0x79, 0x83, 0xa2, 0x28, 0xd0, 0x3e, 0x46, 0x31, 0x33, 0xbb, 0xcb,
|
||||||
0x5d, 0xfe, 0x89, 0xd5, 0x00, 0x49, 0x7a, 0x12, 0xe7, 0xf7, 0x7e, 0xef, 0xcd, 0x9b, 0x37, 0x6f,
|
0x5d, 0xfe, 0xc4, 0x6a, 0x80, 0x38, 0x57, 0xe4, 0x7c, 0xe7, 0x3b, 0x67, 0xce, 0x9c, 0x39, 0x33,
|
||||||
0xde, 0xbc, 0x1d, 0xc1, 0xe6, 0xd0, 0x75, 0x87, 0x0e, 0xbd, 0xe3, 0xf9, 0x6e, 0xe8, 0x9e, 0x8e,
|
0x73, 0x66, 0x16, 0x76, 0x47, 0xb6, 0x3d, 0x32, 0xe9, 0xbe, 0xe3, 0xda, 0xbe, 0x7d, 0x3e, 0x1d,
|
||||||
0x07, 0x77, 0x2c, 0x1a, 0x98, 0xbe, 0xed, 0x85, 0xae, 0xdf, 0x14, 0x18, 0x5e, 0x91, 0x8c, 0x66,
|
0xee, 0xeb, 0xd4, 0xd3, 0x5c, 0xc3, 0xf1, 0x6d, 0xb7, 0xc6, 0x31, 0xbc, 0x21, 0x18, 0xb5, 0x90,
|
||||||
0xcc, 0x68, 0x1c, 0xc2, 0xea, 0x23, 0xdb, 0xa1, 0xed, 0x84, 0xd8, 0xa7, 0x21, 0x7e, 0x08, 0x85,
|
0x51, 0x3d, 0x85, 0xcd, 0x07, 0x86, 0x49, 0x9b, 0x11, 0xb1, 0x4f, 0x7d, 0x7c, 0x1f, 0xb2, 0x43,
|
||||||
0x81, 0xed, 0x50, 0x55, 0xd9, 0xcc, 0x6f, 0x55, 0xb7, 0xaf, 0x35, 0xa7, 0x94, 0x9a, 0x59, 0x8d,
|
0xc3, 0xa4, 0x52, 0x6a, 0x37, 0xb3, 0x57, 0x3a, 0x78, 0xb3, 0x36, 0xa7, 0x54, 0x4b, 0x6a, 0xf4,
|
||||||
0x1e, 0x87, 0x75, 0xa1, 0xd1, 0xf8, 0x67, 0x01, 0xd6, 0xe6, 0x48, 0x31, 0x86, 0x02, 0x23, 0x23,
|
0x18, 0xac, 0x70, 0x8d, 0xea, 0xbf, 0xb3, 0xb0, 0xb5, 0x44, 0x8a, 0x31, 0x64, 0x2d, 0x32, 0x61,
|
||||||
0x6e, 0x51, 0xd9, 0xaa, 0xe8, 0xe2, 0x37, 0x56, 0x61, 0xc9, 0x23, 0xe6, 0x33, 0x32, 0xa4, 0x6a,
|
0x16, 0x53, 0x7b, 0x45, 0x85, 0xff, 0xc7, 0x12, 0xac, 0x39, 0x44, 0x7b, 0x44, 0x46, 0x54, 0x4a,
|
||||||
0x4e, 0xc0, 0xf1, 0x10, 0xbf, 0x07, 0x60, 0x51, 0x8f, 0x32, 0x8b, 0x32, 0xf3, 0x5c, 0xcd, 0x6f,
|
0x73, 0x38, 0x6c, 0xe2, 0xd7, 0x01, 0x74, 0xea, 0x50, 0x4b, 0xa7, 0x96, 0x76, 0x21, 0x65, 0x76,
|
||||||
0xe6, 0xb7, 0x2a, 0x7a, 0x0a, 0xc1, 0xb7, 0x61, 0xd5, 0x1b, 0x9f, 0x3a, 0xb6, 0x69, 0xa4, 0x68,
|
0x33, 0x7b, 0x45, 0x25, 0x86, 0xe0, 0x77, 0x60, 0xd3, 0x99, 0x9e, 0x9b, 0x86, 0xa6, 0xc6, 0x68,
|
||||||
0xb0, 0x99, 0xdf, 0x2a, 0xea, 0x48, 0x0a, 0xda, 0x13, 0xf2, 0x0d, 0x58, 0x79, 0x41, 0xc9, 0xb3,
|
0xb0, 0x9b, 0xd9, 0xcb, 0x29, 0x48, 0x08, 0x9a, 0x33, 0xf2, 0x4d, 0xd8, 0x78, 0x42, 0xc9, 0xa3,
|
||||||
0x34, 0xb5, 0x2a, 0xa8, 0x75, 0x0e, 0xa7, 0x88, 0x7b, 0x50, 0x1b, 0xd1, 0x20, 0x20, 0x43, 0x6a,
|
0x38, 0xb5, 0xc4, 0xa9, 0x15, 0x06, 0xc7, 0x88, 0x0d, 0x28, 0x4f, 0xa8, 0xe7, 0x91, 0x11, 0x55,
|
||||||
0x84, 0xe7, 0x1e, 0x55, 0x0b, 0x62, 0xf5, 0x9b, 0x33, 0xab, 0x9f, 0x5e, 0x79, 0x35, 0xd2, 0x3a,
|
0xfd, 0x0b, 0x87, 0x4a, 0x59, 0x3e, 0xfa, 0xdd, 0x85, 0xd1, 0xcf, 0x8f, 0xbc, 0x14, 0x68, 0x0d,
|
||||||
0x3e, 0xf7, 0x28, 0x6e, 0x41, 0x85, 0xb2, 0xf1, 0x48, 0x5a, 0x28, 0x2e, 0x88, 0x9f, 0xc6, 0xc6,
|
0x2e, 0x1c, 0x8a, 0xeb, 0x50, 0xa4, 0xd6, 0x74, 0x22, 0x2c, 0xe4, 0x56, 0xc4, 0x4f, 0xb6, 0xa6,
|
||||||
0xa3, 0x69, 0x2b, 0x65, 0xae, 0x16, 0x99, 0x58, 0x0a, 0xa8, 0xff, 0xdc, 0x36, 0xa9, 0x5a, 0x12,
|
0x93, 0x79, 0x2b, 0x05, 0xa6, 0x16, 0x98, 0x58, 0xf3, 0xa8, 0xfb, 0xd8, 0xd0, 0xa8, 0x94, 0xe7,
|
||||||
0x06, 0x6e, 0xcc, 0x18, 0xe8, 0x4b, 0xf9, 0xb4, 0x8d, 0x58, 0x0f, 0xef, 0x41, 0x85, 0xbe, 0x0c,
|
0x06, 0x6e, 0x2e, 0x18, 0xe8, 0x0b, 0xf9, 0xbc, 0x8d, 0x50, 0x0f, 0x37, 0xa0, 0x48, 0x9f, 0xfa,
|
||||||
0x29, 0x0b, 0x6c, 0x97, 0xa9, 0x4b, 0xc2, 0xc8, 0xf5, 0x39, 0xbb, 0x48, 0x1d, 0x6b, 0xda, 0xc4,
|
0xd4, 0xf2, 0x0c, 0xdb, 0x92, 0xd6, 0xb8, 0x91, 0xb7, 0x96, 0xcc, 0x22, 0x35, 0xf5, 0x79, 0x13,
|
||||||
0x44, 0x0f, 0x3f, 0x80, 0x25, 0xd7, 0x0b, 0x6d, 0x97, 0x05, 0x6a, 0x79, 0x53, 0xd9, 0xaa, 0x6e,
|
0x33, 0x3d, 0x7c, 0x0f, 0xd6, 0x6c, 0xc7, 0x37, 0x6c, 0xcb, 0x93, 0x0a, 0xbb, 0xa9, 0xbd, 0xd2,
|
||||||
0xbf, 0x33, 0x37, 0x11, 0xba, 0x92, 0xa3, 0xc7, 0x64, 0xdc, 0x01, 0x14, 0xb8, 0x63, 0xdf, 0xa4,
|
0xc1, 0xab, 0x4b, 0x13, 0xa1, 0x2b, 0x38, 0x4a, 0x48, 0xc6, 0x2d, 0x40, 0x9e, 0x3d, 0x75, 0x35,
|
||||||
0x86, 0xe9, 0x5a, 0xd4, 0xb0, 0xd9, 0xc0, 0x55, 0x2b, 0xc2, 0xc0, 0x95, 0xd9, 0x85, 0x08, 0xe2,
|
0xaa, 0x6a, 0xb6, 0x4e, 0x55, 0xc3, 0x1a, 0xda, 0x52, 0x91, 0x1b, 0xb8, 0xbe, 0x38, 0x10, 0x4e,
|
||||||
0x9e, 0x6b, 0xd1, 0x0e, 0x1b, 0xb8, 0x7a, 0x3d, 0xc8, 0x8c, 0xf1, 0x25, 0x28, 0x05, 0xe7, 0x2c,
|
0x6c, 0xd8, 0x3a, 0x6d, 0x59, 0x43, 0x5b, 0xa9, 0x78, 0x89, 0x36, 0xbe, 0x02, 0x79, 0xef, 0xc2,
|
||||||
0x24, 0x2f, 0xd5, 0x9a, 0xc8, 0x90, 0x68, 0xd4, 0xf8, 0x4f, 0x11, 0x56, 0x2e, 0x92, 0x62, 0x9f,
|
0xf2, 0xc9, 0x53, 0xa9, 0xcc, 0x33, 0x24, 0x68, 0x55, 0xbf, 0xcd, 0xc3, 0xc6, 0x65, 0x52, 0xec,
|
||||||
0x40, 0x71, 0xc0, 0x57, 0xa9, 0xe6, 0xfe, 0x97, 0x18, 0x48, 0x9d, 0x6c, 0x10, 0x4b, 0xdf, 0x32,
|
0x23, 0xc8, 0x0d, 0xd9, 0x28, 0xa5, 0xf4, 0xff, 0x13, 0x03, 0xa1, 0x93, 0x0c, 0x62, 0xfe, 0x07,
|
||||||
0x88, 0x2d, 0xa8, 0x32, 0x1a, 0x84, 0xd4, 0x92, 0x19, 0x91, 0xbf, 0x60, 0x4e, 0x81, 0x54, 0x9a,
|
0x06, 0xb1, 0x0e, 0x25, 0x8b, 0x7a, 0x3e, 0xd5, 0x45, 0x46, 0x64, 0x2e, 0x99, 0x53, 0x20, 0x94,
|
||||||
0x4d, 0xa9, 0xc2, 0xb7, 0x4a, 0xa9, 0x27, 0xb0, 0x92, 0xb8, 0x64, 0xf8, 0x84, 0x0d, 0xe3, 0xdc,
|
0x16, 0x53, 0x2a, 0xfb, 0x83, 0x52, 0xea, 0x33, 0xd8, 0x88, 0x5c, 0x52, 0x5d, 0x62, 0x8d, 0xc2,
|
||||||
0xbc, 0xf3, 0x3a, 0x4f, 0x9a, 0x5a, 0xac, 0xa7, 0x73, 0x35, 0xbd, 0x4e, 0x33, 0x63, 0xdc, 0x06,
|
0xdc, 0xdc, 0x7f, 0x9e, 0x27, 0x35, 0x39, 0xd4, 0x53, 0x98, 0x9a, 0x52, 0xa1, 0x89, 0x36, 0x6e,
|
||||||
0x70, 0x19, 0x75, 0x07, 0x86, 0x45, 0x4d, 0x47, 0x2d, 0x2f, 0x88, 0x52, 0x97, 0x53, 0x66, 0xa2,
|
0x02, 0xd8, 0x16, 0xb5, 0x87, 0xaa, 0x4e, 0x35, 0x53, 0x2a, 0xac, 0x88, 0x52, 0x97, 0x51, 0x16,
|
||||||
0xe4, 0x4a, 0xd4, 0x74, 0xf0, 0xc7, 0x93, 0x54, 0x5b, 0x5a, 0x90, 0x29, 0x87, 0xf2, 0x90, 0xcd,
|
0xa2, 0x64, 0x0b, 0x54, 0x33, 0xf1, 0x87, 0xb3, 0x54, 0x5b, 0x5b, 0x91, 0x29, 0xa7, 0x62, 0x91,
|
||||||
0x64, 0xdb, 0x09, 0xd4, 0x7d, 0xca, 0xf3, 0x9e, 0x5a, 0xd1, 0xca, 0x2a, 0xc2, 0x89, 0xe6, 0x6b,
|
0x2d, 0x64, 0xdb, 0x19, 0x54, 0x5c, 0xca, 0xf2, 0x9e, 0xea, 0xc1, 0xc8, 0x8a, 0xdc, 0x89, 0xda,
|
||||||
0x57, 0xa6, 0x47, 0x6a, 0x72, 0x61, 0xcb, 0x7e, 0x7a, 0x88, 0xdf, 0x87, 0x04, 0x30, 0x44, 0x5a,
|
0x73, 0x47, 0xa6, 0x04, 0x6a, 0x62, 0x60, 0xeb, 0x6e, 0xbc, 0x89, 0xdf, 0x80, 0x08, 0x50, 0x79,
|
||||||
0x81, 0xa8, 0x42, 0xb5, 0x18, 0x3c, 0x22, 0x23, 0xba, 0xf1, 0x10, 0xea, 0xd9, 0xf0, 0xe0, 0x75,
|
0x5a, 0x01, 0xdf, 0x85, 0xca, 0x21, 0xd8, 0x21, 0x13, 0xba, 0xf3, 0x15, 0x54, 0x92, 0xe1, 0xc1,
|
||||||
0x28, 0x06, 0x21, 0xf1, 0x43, 0x91, 0x85, 0x45, 0x5d, 0x0e, 0x30, 0x82, 0x3c, 0x65, 0x96, 0xa8,
|
0xdb, 0x90, 0xf3, 0x7c, 0xe2, 0xfa, 0x3c, 0x0b, 0x73, 0x8a, 0x68, 0x60, 0x04, 0x19, 0x6a, 0xe9,
|
||||||
0x72, 0x45, 0x9d, 0xff, 0xdc, 0xf8, 0x08, 0x96, 0x33, 0xd3, 0x5f, 0x54, 0xb1, 0xf1, 0xdb, 0x12,
|
0x7c, 0x97, 0xcb, 0x29, 0xec, 0x2f, 0xfe, 0xe5, 0x6c, 0xc0, 0x19, 0x3e, 0xe0, 0xb7, 0x17, 0x67,
|
||||||
0xac, 0xcf, 0xcb, 0xb9, 0xb9, 0xe9, 0x7f, 0x09, 0x4a, 0x6c, 0x3c, 0x3a, 0xa5, 0xbe, 0x9a, 0x17,
|
0x34, 0x61, 0x79, 0x7e, 0xdc, 0x3b, 0x1f, 0xc0, 0x7a, 0x62, 0x00, 0x97, 0xed, 0xba, 0xfa, 0x5b,
|
||||||
0x16, 0xa2, 0x11, 0x6e, 0x41, 0xd1, 0x21, 0xa7, 0xd4, 0x51, 0x0b, 0x9b, 0xca, 0x56, 0x7d, 0xfb,
|
0x78, 0x79, 0xa9, 0x69, 0xfc, 0x19, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x65,
|
||||||
0xf6, 0x85, 0xb2, 0xba, 0x79, 0xc0, 0x55, 0x74, 0xa9, 0x89, 0x3f, 0x85, 0x42, 0x54, 0xe2, 0xb8,
|
0xac, 0xe8, 0x4a, 0xfa, 0xcf, 0xda, 0x8a, 0x9c, 0x3b, 0x8b, 0xb3, 0x85, 0x15, 0x65, 0x6b, 0xba,
|
||||||
0x85, 0x5b, 0x17, 0xb3, 0xc0, 0x73, 0x51, 0x17, 0x7a, 0xf8, 0x6d, 0xa8, 0xf0, 0xbf, 0x32, 0xb6,
|
0x08, 0xde, 0x2e, 0x16, 0xfe, 0xbb, 0x86, 0x9e, 0x3d, 0x7b, 0xf6, 0x2c, 0x5d, 0xfd, 0x63, 0x1e,
|
||||||
0x25, 0xe1, 0x73, 0x99, 0x03, 0x3c, 0xae, 0x78, 0x03, 0xca, 0x22, 0xcd, 0x2c, 0x1a, 0x5f, 0x0d,
|
0xb6, 0x97, 0xad, 0x99, 0xa5, 0xcb, 0xf7, 0x0a, 0xe4, 0xad, 0xe9, 0xe4, 0x9c, 0xba, 0x3c, 0x48,
|
||||||
0xc9, 0x98, 0x6f, 0x8c, 0x45, 0x07, 0x64, 0xec, 0x84, 0xc6, 0x73, 0xe2, 0x8c, 0xa9, 0x48, 0x98,
|
0x39, 0x25, 0x68, 0xe1, 0x3a, 0xe4, 0x4c, 0x72, 0x4e, 0x4d, 0x29, 0xbb, 0x9b, 0xda, 0xab, 0x1c,
|
||||||
0x8a, 0x5e, 0x8b, 0xc0, 0x9f, 0x73, 0x0c, 0x5f, 0x81, 0xaa, 0xcc, 0x4a, 0x9b, 0x59, 0xf4, 0xa5,
|
0xbc, 0x73, 0xa9, 0x55, 0x59, 0x6b, 0x33, 0x15, 0x45, 0x68, 0xe2, 0x8f, 0x21, 0x1b, 0x6c, 0xd1,
|
||||||
0xa8, 0x3e, 0x45, 0x5d, 0x26, 0x6a, 0x87, 0x23, 0x7c, 0xfa, 0xa7, 0x81, 0xcb, 0xe2, 0xad, 0x15,
|
0xcc, 0xc2, 0xed, 0xcb, 0x59, 0x60, 0x6b, 0x49, 0xe1, 0x7a, 0xf8, 0x15, 0x28, 0xb2, 0x5f, 0x91,
|
||||||
0x53, 0x70, 0x40, 0x4c, 0xff, 0xd1, 0x74, 0xe1, 0x7b, 0x77, 0xfe, 0xf2, 0xa6, 0x73, 0xb1, 0xf1,
|
0x1b, 0x79, 0xee, 0x73, 0x81, 0x01, 0x2c, 0x2f, 0xf0, 0x0e, 0x14, 0xf8, 0x32, 0xd1, 0x69, 0x78,
|
||||||
0xe7, 0x1c, 0x14, 0xc4, 0x79, 0x5b, 0x81, 0xea, 0xf1, 0xe7, 0x3d, 0xcd, 0x68, 0x77, 0x4f, 0x76,
|
0xb4, 0x45, 0x6d, 0x96, 0x58, 0x3a, 0x1d, 0x92, 0xa9, 0xe9, 0xab, 0x8f, 0x89, 0x39, 0xa5, 0x3c,
|
||||||
0x0f, 0x34, 0xa4, 0xe0, 0x3a, 0x80, 0x00, 0x1e, 0x1d, 0x74, 0x5b, 0xc7, 0x28, 0x97, 0x8c, 0x3b,
|
0xe1, 0x8b, 0x4a, 0x39, 0x00, 0x7f, 0xc3, 0x30, 0x7c, 0x1d, 0x4a, 0x62, 0x55, 0x19, 0x96, 0x4e,
|
||||||
0x47, 0xc7, 0x0f, 0xee, 0xa1, 0x7c, 0xa2, 0x70, 0x22, 0x81, 0x42, 0x9a, 0x70, 0x77, 0x1b, 0x15,
|
0x9f, 0xf2, 0xdd, 0x33, 0xa7, 0x88, 0x85, 0xd6, 0x62, 0x08, 0xeb, 0xfe, 0xa1, 0x67, 0x5b, 0x61,
|
||||||
0x31, 0x82, 0x9a, 0x34, 0xd0, 0x79, 0xa2, 0xb5, 0x1f, 0xdc, 0x43, 0xa5, 0x2c, 0x72, 0x77, 0x1b,
|
0x6a, 0xf2, 0x2e, 0x18, 0xc0, 0xbb, 0xff, 0x60, 0x7e, 0xe3, 0x7e, 0x6d, 0xf9, 0xf0, 0xe6, 0x73,
|
||||||
0x2d, 0xe1, 0x65, 0xa8, 0x08, 0x64, 0xb7, 0xdb, 0x3d, 0x40, 0xe5, 0xc4, 0x66, 0xff, 0x58, 0xef,
|
0xaa, 0xfa, 0xb7, 0x34, 0x64, 0xf9, 0x7e, 0xb1, 0x01, 0xa5, 0xc1, 0xe7, 0x3d, 0x59, 0x6d, 0x76,
|
||||||
0x1c, 0xed, 0xa3, 0x4a, 0x62, 0x73, 0x5f, 0xef, 0x9e, 0xf4, 0x10, 0x24, 0x16, 0x0e, 0xb5, 0x7e,
|
0xcf, 0x8e, 0xda, 0x32, 0x4a, 0xe1, 0x0a, 0x00, 0x07, 0x1e, 0xb4, 0xbb, 0xf5, 0x01, 0x4a, 0x47,
|
||||||
0xbf, 0xb5, 0xaf, 0xa1, 0x6a, 0xc2, 0xd8, 0xfd, 0xfc, 0x58, 0xeb, 0xa3, 0x5a, 0xc6, 0xad, 0xbb,
|
0xed, 0x56, 0x67, 0x70, 0xef, 0x0e, 0xca, 0x44, 0x0a, 0x67, 0x02, 0xc8, 0xc6, 0x09, 0xef, 0x1f,
|
||||||
0xdb, 0x68, 0x39, 0x99, 0x42, 0x3b, 0x3a, 0x39, 0x44, 0x75, 0xbc, 0x0a, 0xcb, 0x72, 0x8a, 0xd8,
|
0xa0, 0x1c, 0x46, 0x50, 0x16, 0x06, 0x5a, 0x9f, 0xc9, 0xcd, 0x7b, 0x77, 0x50, 0x3e, 0x89, 0xbc,
|
||||||
0x89, 0x95, 0x29, 0xe8, 0xc1, 0x3d, 0x84, 0x26, 0x8e, 0x48, 0x2b, 0xab, 0x19, 0xe0, 0xc1, 0x3d,
|
0x7f, 0x80, 0xd6, 0xf0, 0x3a, 0x14, 0x39, 0x72, 0xd4, 0xed, 0xb6, 0x51, 0x21, 0xb2, 0xd9, 0x1f,
|
||||||
0x84, 0x1b, 0x7b, 0x50, 0x14, 0xd9, 0x85, 0x31, 0xd4, 0x0f, 0x5a, 0xbb, 0xda, 0x81, 0xd1, 0xed,
|
0x28, 0xad, 0xce, 0x31, 0x2a, 0x46, 0x36, 0x8f, 0x95, 0xee, 0x59, 0x0f, 0x41, 0x64, 0xe1, 0x54,
|
||||||
0x1d, 0x77, 0xba, 0x47, 0xad, 0x03, 0xa4, 0x4c, 0x30, 0x5d, 0xfb, 0xd9, 0x49, 0x47, 0xd7, 0xda,
|
0xee, 0xf7, 0xeb, 0xc7, 0x32, 0x2a, 0x45, 0x8c, 0xa3, 0xcf, 0x07, 0x72, 0x1f, 0x95, 0x13, 0x6e,
|
||||||
0x28, 0x97, 0xc6, 0x7a, 0x5a, 0xeb, 0x58, 0x6b, 0xa3, 0x7c, 0xc3, 0x84, 0xf5, 0x79, 0x75, 0x66,
|
0xbd, 0x7f, 0x80, 0xd6, 0xa3, 0x2e, 0xe4, 0xce, 0xd9, 0x29, 0xaa, 0xe0, 0x4d, 0x58, 0x17, 0x5d,
|
||||||
0xee, 0xc9, 0x48, 0x6d, 0x71, 0x6e, 0xc1, 0x16, 0x0b, 0x5b, 0x33, 0x5b, 0xfc, 0x95, 0x02, 0x6b,
|
0x84, 0x4e, 0x6c, 0xcc, 0x41, 0xf7, 0xee, 0x20, 0x34, 0x73, 0x44, 0x58, 0xd9, 0x4c, 0x00, 0xf7,
|
||||||
0x73, 0x6a, 0xed, 0xdc, 0x49, 0x7e, 0x0a, 0x45, 0x99, 0xa2, 0xf2, 0xf6, 0xb9, 0x39, 0xb7, 0x68,
|
0xee, 0x20, 0x5c, 0x6d, 0x40, 0x8e, 0x67, 0x17, 0xc6, 0x50, 0x69, 0xd7, 0x8f, 0xe4, 0xb6, 0xda,
|
||||||
0x8b, 0x84, 0x9d, 0xb9, 0x81, 0x84, 0x5e, 0xfa, 0x06, 0xce, 0x2f, 0xb8, 0x81, 0xb9, 0x89, 0x19,
|
0xed, 0x0d, 0x5a, 0xdd, 0x4e, 0xbd, 0x8d, 0x52, 0x33, 0x4c, 0x91, 0x7f, 0x7d, 0xd6, 0x52, 0xe4,
|
||||||
0x27, 0x7f, 0xa5, 0x80, 0xba, 0xc8, 0xf6, 0x6b, 0x0a, 0x45, 0x2e, 0x53, 0x28, 0x3e, 0x99, 0x76,
|
0x26, 0x4a, 0xc7, 0xb1, 0x9e, 0x5c, 0x1f, 0xc8, 0x4d, 0x94, 0xa9, 0x6a, 0xb0, 0xbd, 0x6c, 0x9f,
|
||||||
0xe0, 0xea, 0xe2, 0x35, 0xcc, 0x78, 0xf1, 0xb5, 0x02, 0x97, 0xe6, 0x37, 0x2a, 0x73, 0x7d, 0xf8,
|
0x5c, 0xba, 0x32, 0x62, 0x53, 0x9c, 0x5e, 0x31, 0xc5, 0xdc, 0xd6, 0xc2, 0x14, 0x7f, 0x9d, 0x82,
|
||||||
0x14, 0x4a, 0x23, 0x1a, 0x9e, 0xb9, 0xf1, 0x65, 0xfd, 0xc1, 0x9c, 0x2b, 0x80, 0x8b, 0xa7, 0x63,
|
0xad, 0x25, 0x67, 0xc5, 0xd2, 0x4e, 0x7e, 0x01, 0x39, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb5, 0xf4,
|
||||||
0x15, 0x69, 0xa5, 0xef, 0x90, 0xfc, 0xa2, 0x6e, 0x43, 0x7a, 0x33, 0xe3, 0xe9, 0xaf, 0x73, 0xf0,
|
0xd0, 0xe1, 0x09, 0xbb, 0x70, 0x82, 0x72, 0xbd, 0x78, 0x05, 0x91, 0x59, 0x51, 0x41, 0x30, 0x13,
|
||||||
0xe6, 0x5c, 0xe3, 0x73, 0x1d, 0x7d, 0x17, 0xc0, 0x66, 0xde, 0x38, 0x94, 0x17, 0xb2, 0xac, 0x4f,
|
0x0b, 0x4e, 0xfe, 0x2e, 0x05, 0xd2, 0x2a, 0xdb, 0xcf, 0xd9, 0x28, 0xd2, 0x89, 0x8d, 0xe2, 0xa3,
|
||||||
0x15, 0x81, 0x88, 0xb3, 0xcf, 0x6b, 0xcf, 0x38, 0x4c, 0xe4, 0x79, 0x21, 0x07, 0x09, 0x09, 0xc2,
|
0x79, 0x07, 0x6e, 0xac, 0x1e, 0xc3, 0x82, 0x17, 0xdf, 0xa4, 0xe0, 0xca, 0xf2, 0x42, 0x6b, 0xa9,
|
||||||
0xc3, 0x89, 0xa3, 0x05, 0xe1, 0xe8, 0x7b, 0x0b, 0x56, 0x3a, 0x73, 0xd7, 0x7d, 0x08, 0xc8, 0x74,
|
0x0f, 0x1f, 0x43, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x16, 0x1b, 0x6f, 0x2f, 0x39, 0xc2, 0x98, 0x78,
|
||||||
0x6c, 0xca, 0x42, 0x23, 0x08, 0x7d, 0x4a, 0x46, 0x36, 0x1b, 0x8a, 0x02, 0x5c, 0xde, 0x29, 0x0e,
|
0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xcc, 0xac, 0xaa, 0x96, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x3e,
|
||||||
0x88, 0x13, 0x50, 0x7d, 0x45, 0x8a, 0xfb, 0xb1, 0x94, 0x6b, 0x88, 0x5b, 0xc6, 0x4f, 0x69, 0x94,
|
0x0d, 0x2f, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xd7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xa2, 0xa0, 0x10,
|
||||||
0x32, 0x1a, 0x52, 0x9c, 0x68, 0x34, 0x7e, 0xb3, 0x04, 0xd5, 0x54, 0x5b, 0x87, 0xaf, 0x42, 0xed,
|
0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80,
|
||||||
0x29, 0x79, 0x4e, 0x8c, 0xb8, 0x55, 0x97, 0x91, 0xa8, 0x72, 0xac, 0x17, 0xb5, 0xeb, 0x1f, 0xc2,
|
0x38, 0xe1, 0xfe, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xf5, 0x15, 0x23, 0x5d, 0x38, 0xab, 0xdf, 0x03,
|
||||||
0xba, 0xa0, 0xb8, 0xe3, 0x90, 0xfa, 0x86, 0xe9, 0x90, 0x20, 0x10, 0x41, 0x2b, 0x0b, 0x2a, 0xe6,
|
0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1,
|
||||||
0xb2, 0x2e, 0x17, 0xed, 0xc5, 0x12, 0x7c, 0x1f, 0xd6, 0x84, 0xc6, 0x68, 0xec, 0x84, 0xb6, 0xe7,
|
0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0xcf, 0x38, 0x37,
|
||||||
0x50, 0x83, 0x7f, 0x3c, 0x04, 0xa2, 0x10, 0x27, 0x9e, 0xad, 0x72, 0xc6, 0x61, 0x44, 0xe0, 0x1e,
|
0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0xb6, 0x00, 0xa5, 0x58, 0x59, 0x8a, 0x6f,
|
||||||
0x05, 0xb8, 0x0d, 0xef, 0x0a, 0xb5, 0x21, 0x65, 0xd4, 0x27, 0x21, 0x35, 0xe8, 0x2f, 0xc7, 0xc4,
|
0x40, 0xf9, 0x21, 0x79, 0x4c, 0xd4, 0xf0, 0xaa, 0x21, 0x22, 0x51, 0x62, 0x58, 0x2f, 0xb8, 0x6e,
|
||||||
0x09, 0x0c, 0xc2, 0x2c, 0xe3, 0x8c, 0x04, 0x67, 0xea, 0x3a, 0x37, 0xb0, 0x9b, 0x53, 0x15, 0xfd,
|
0xbc, 0x07, 0xdb, 0x9c, 0x62, 0x4f, 0x7d, 0xea, 0xaa, 0x9a, 0x49, 0x3c, 0x8f, 0x07, 0xad, 0xc0,
|
||||||
0x32, 0x27, 0xee, 0x47, 0x3c, 0x4d, 0xd0, 0x5a, 0xcc, 0xfa, 0x8c, 0x04, 0x67, 0x78, 0x07, 0x2e,
|
0xa9, 0x98, 0xc9, 0xba, 0x4c, 0xd4, 0x08, 0x25, 0xf8, 0x2e, 0x6c, 0x71, 0x8d, 0xc9, 0xd4, 0xf4,
|
||||||
0x09, 0x2b, 0x41, 0xe8, 0xdb, 0x6c, 0x68, 0x98, 0x67, 0xd4, 0x7c, 0x66, 0x8c, 0xc3, 0xc1, 0x43,
|
0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xfc, 0x78, 0x7c, 0x23, 0x8e, 0x3c, 0xdb, 0x64, 0x8c, 0xd3, 0x80,
|
||||||
0xf5, 0xed, 0xf4, 0xfc, 0xc2, 0xc3, 0xbe, 0xe0, 0xec, 0x71, 0xca, 0x49, 0x38, 0x78, 0x88, 0xfb,
|
0xc0, 0x3c, 0xf2, 0x70, 0x13, 0x5e, 0xe3, 0x6a, 0x23, 0x6a, 0x51, 0x97, 0xf8, 0x54, 0xa5, 0x5f,
|
||||||
0x50, 0xe3, 0x9b, 0x31, 0xb2, 0xbf, 0xa4, 0xc6, 0xc0, 0xf5, 0xc5, 0xcd, 0x52, 0x9f, 0x73, 0xb2,
|
0x4e, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x31, 0xf1, 0xc6, 0xd2, 0x36, 0x33, 0x70, 0x94, 0x96,
|
||||||
0x53, 0x11, 0x6c, 0x76, 0x23, 0x85, 0x43, 0xd7, 0xa2, 0x3b, 0xc5, 0x7e, 0x4f, 0xd3, 0xda, 0x7a,
|
0x52, 0xca, 0x35, 0x46, 0x3c, 0x0e, 0x78, 0x32, 0xa7, 0xd5, 0x2d, 0xfd, 0x13, 0xe2, 0x8d, 0xf1,
|
||||||
0x35, 0xb6, 0xf2, 0xc8, 0xf5, 0x79, 0x42, 0x0d, 0xdd, 0x24, 0xc0, 0x55, 0x99, 0x50, 0x43, 0x37,
|
0x21, 0x5c, 0xe1, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x91, 0xaa, 0x8d, 0xa9, 0xf6, 0x48, 0x9d, 0xfa,
|
||||||
0x0e, 0xef, 0x7d, 0x58, 0x33, 0x4d, 0xb9, 0x66, 0xdb, 0x34, 0xa2, 0x16, 0x3f, 0x50, 0x51, 0x26,
|
0xc3, 0xfb, 0xd2, 0x2b, 0xf1, 0xfe, 0xb9, 0x87, 0x7d, 0xce, 0x69, 0x30, 0xca, 0x99, 0x3f, 0xbc,
|
||||||
0x58, 0xa6, 0xb9, 0x2f, 0x09, 0x51, 0x8e, 0x07, 0xf8, 0x63, 0x78, 0x73, 0x12, 0xac, 0xb4, 0xe2,
|
0x8f, 0xfb, 0x50, 0x66, 0x93, 0x31, 0x31, 0xbe, 0xa2, 0xea, 0xd0, 0x76, 0xf9, 0xc9, 0x52, 0x59,
|
||||||
0xea, 0xcc, 0x2a, 0xa7, 0x55, 0xef, 0xc3, 0x9a, 0x77, 0x3e, 0xab, 0x88, 0x33, 0x33, 0x7a, 0xe7,
|
0xb2, 0xb2, 0x63, 0x11, 0xac, 0x75, 0x03, 0x85, 0x53, 0x5b, 0xa7, 0x87, 0xb9, 0x7e, 0x4f, 0x96,
|
||||||
0xd3, 0x6a, 0xd7, 0xc5, 0x67, 0x9b, 0x4f, 0x4d, 0x12, 0x52, 0x4b, 0x7d, 0x2b, 0xcd, 0x4e, 0x09,
|
0x9b, 0x4a, 0x29, 0xb4, 0xf2, 0xc0, 0x76, 0x59, 0x42, 0x8d, 0xec, 0x28, 0xc0, 0x25, 0x91, 0x50,
|
||||||
0xf0, 0x1d, 0x40, 0xa6, 0x69, 0x50, 0x46, 0x4e, 0x1d, 0x6a, 0x10, 0x9f, 0x32, 0x12, 0xa8, 0x57,
|
0x23, 0x3b, 0x0c, 0xef, 0x5d, 0xd8, 0xd2, 0x34, 0x31, 0x66, 0x43, 0x53, 0x83, 0x2b, 0x8a, 0x27,
|
||||||
0xd2, 0xe4, 0xba, 0x69, 0x6a, 0x42, 0xda, 0x12, 0x42, 0x7c, 0x0b, 0x56, 0xdd, 0xd3, 0xa7, 0xa6,
|
0xa1, 0x44, 0xb0, 0x34, 0xed, 0x58, 0x10, 0x82, 0x1c, 0xf7, 0xf0, 0x87, 0xf0, 0xf2, 0x2c, 0x58,
|
||||||
0xcc, 0x2c, 0xc3, 0xf3, 0xe9, 0xc0, 0x7e, 0xa9, 0x5e, 0x13, 0x61, 0x5a, 0xe1, 0x02, 0x91, 0x57,
|
0x71, 0xc5, 0xcd, 0x85, 0x51, 0xce, 0xab, 0xde, 0x85, 0x2d, 0xe7, 0x62, 0x51, 0x11, 0x27, 0x7a,
|
||||||
0x3d, 0x01, 0xe3, 0x9b, 0x80, 0xcc, 0xe0, 0x8c, 0xf8, 0x9e, 0xb8, 0xda, 0x03, 0x8f, 0x98, 0x54,
|
0x74, 0x2e, 0xe6, 0xd5, 0x3e, 0x80, 0x6d, 0x67, 0xec, 0x2c, 0xea, 0xdd, 0x8e, 0xeb, 0x61, 0x67,
|
||||||
0xbd, 0x2e, 0xa9, 0x12, 0x3f, 0x8a, 0x61, 0xfc, 0x04, 0xd6, 0xc7, 0xcc, 0x66, 0x21, 0xf5, 0x3d,
|
0xec, 0xcc, 0x2b, 0xbe, 0xc5, 0xef, 0xab, 0x2e, 0xd5, 0x88, 0x4f, 0x75, 0xe9, 0x6a, 0x9c, 0x1e,
|
||||||
0x9f, 0xf2, 0x0e, 0x5d, 0x1e, 0x33, 0xf5, 0x5f, 0x4b, 0x0b, 0x7a, 0xec, 0x93, 0x34, 0x5b, 0xee,
|
0x13, 0xe0, 0x7d, 0x40, 0x9a, 0xa6, 0x52, 0x8b, 0x9c, 0x9b, 0x54, 0x25, 0x2e, 0xb5, 0x88, 0x27,
|
||||||
0xae, 0xbe, 0x36, 0x9e, 0x05, 0x1b, 0x3b, 0x50, 0x4b, 0x6f, 0x3a, 0xae, 0x80, 0xdc, 0x76, 0xa4,
|
0x5d, 0x8f, 0x93, 0x2b, 0x9a, 0x26, 0x73, 0x69, 0x9d, 0x0b, 0xf1, 0x6d, 0xd8, 0xb4, 0xcf, 0x1f,
|
||||||
0xf0, 0x0b, 0x74, 0xaf, 0xdb, 0xe6, 0x57, 0xdf, 0x17, 0x1a, 0xca, 0xf1, 0x2b, 0xf8, 0xa0, 0x73,
|
0x6a, 0x22, 0x25, 0x55, 0xc7, 0xa5, 0x43, 0xe3, 0xa9, 0xf4, 0x26, 0x8f, 0xef, 0x06, 0x13, 0xf0,
|
||||||
0xac, 0x19, 0xfa, 0xc9, 0xd1, 0x71, 0xe7, 0x50, 0x43, 0xf9, 0x5b, 0x95, 0xf2, 0xbf, 0x97, 0xd0,
|
0x84, 0xec, 0x71, 0x18, 0xdf, 0x02, 0xa4, 0x79, 0x63, 0xe2, 0x3a, 0xbc, 0x26, 0xf0, 0x1c, 0xa2,
|
||||||
0xab, 0x57, 0xaf, 0x5e, 0xe5, 0x1e, 0x17, 0xca, 0x1f, 0xa0, 0x1b, 0x8d, 0xbf, 0xe6, 0xa0, 0x9e,
|
0x51, 0xe9, 0x2d, 0x41, 0x15, 0x78, 0x27, 0x84, 0xd9, 0x92, 0xf0, 0x9e, 0x18, 0x43, 0x3f, 0xb4,
|
||||||
0x6d, 0x7e, 0xf1, 0x4f, 0xe0, 0xad, 0xf8, 0x4b, 0x35, 0xa0, 0xa1, 0xf1, 0xc2, 0xf6, 0x45, 0x36,
|
0x78, 0x53, 0x2c, 0x09, 0x8e, 0x05, 0xd6, 0xf6, 0x00, 0xb1, 0x50, 0x24, 0x3a, 0xde, 0xe3, 0xb4,
|
||||||
0x8e, 0x88, 0x6c, 0x1f, 0x93, 0x40, 0xae, 0x47, 0xac, 0x3e, 0x0d, 0x7f, 0x61, 0xfb, 0x3c, 0xd7,
|
0x8a, 0x33, 0x76, 0xe2, 0xfd, 0xbe, 0x01, 0xeb, 0x8c, 0x39, 0xeb, 0xf4, 0x96, 0xa8, 0x67, 0x9c,
|
||||||
0x46, 0x24, 0xc4, 0x07, 0x70, 0x85, 0xb9, 0x46, 0x10, 0x12, 0x66, 0x11, 0xdf, 0x32, 0x26, 0x6f,
|
0x71, 0xac, 0xc7, 0x1f, 0xad, 0xb4, 0xac, 0x1e, 0x42, 0x39, 0x9e, 0x9f, 0xb8, 0x08, 0x22, 0x43,
|
||||||
0x04, 0x06, 0x31, 0x4d, 0x1a, 0x04, 0xae, 0xbc, 0x05, 0x12, 0x2b, 0xef, 0x30, 0xb7, 0x1f, 0x91,
|
0x51, 0x8a, 0x9d, 0xf5, 0x8d, 0x6e, 0x93, 0x9d, 0xd2, 0x5f, 0xc8, 0x28, 0xcd, 0xaa, 0x85, 0x76,
|
||||||
0x27, 0xe5, 0xb1, 0x15, 0x51, 0xa7, 0x36, 0x3d, 0xbf, 0x68, 0xd3, 0xdf, 0x86, 0xca, 0x88, 0x78,
|
0x6b, 0x20, 0xab, 0xca, 0x59, 0x67, 0xd0, 0x3a, 0x95, 0x51, 0x26, 0x56, 0x96, 0x9e, 0x64, 0x0b,
|
||||||
0x06, 0x65, 0xa1, 0x7f, 0x2e, 0x5a, 0xb6, 0xb2, 0x5e, 0x1e, 0x11, 0x4f, 0xe3, 0xe3, 0xef, 0x6e,
|
0x6f, 0xa3, 0x9b, 0xd5, 0xef, 0xd2, 0x50, 0x49, 0xde, 0x33, 0xf0, 0xcf, 0xe1, 0x6a, 0xf8, 0x28,
|
||||||
0x27, 0xb2, 0xd1, 0x2c, 0xa3, 0x4a, 0xe3, 0x1f, 0x79, 0xa8, 0xa5, 0x9b, 0x37, 0xde, 0x0b, 0x9b,
|
0xe0, 0x51, 0x5f, 0x7d, 0x62, 0xb8, 0x7c, 0xe1, 0x4c, 0x88, 0xa8, 0xb3, 0xa3, 0xa9, 0xdb, 0x0e,
|
||||||
0xa2, 0x50, 0x2b, 0xe2, 0x28, 0xbf, 0xff, 0x8d, 0xad, 0x5e, 0x73, 0x8f, 0x57, 0xf0, 0x9d, 0x92,
|
0x58, 0x7d, 0xea, 0x7f, 0x6a, 0xb8, 0x6c, 0x59, 0x4c, 0x88, 0x8f, 0xdb, 0x70, 0xdd, 0xb2, 0x55,
|
||||||
0x6c, 0xa9, 0x74, 0xa9, 0xc9, 0x6f, 0x4f, 0x7e, 0x78, 0xa9, 0x6c, 0xd4, 0xcb, 0x7a, 0x34, 0xc2,
|
0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3d, 0xc7, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xe2,
|
||||||
0xfb, 0x50, 0x7a, 0x1a, 0x08, 0xdb, 0x25, 0x61, 0xfb, 0xda, 0x37, 0xdb, 0x7e, 0xdc, 0x17, 0xc6,
|
0xc0, 0x8a, 0xac, 0xbc, 0x6a, 0xd9, 0xfd, 0x80, 0x3c, 0xdb, 0xc9, 0xeb, 0x01, 0x75, 0x2e, 0xcd,
|
||||||
0x2b, 0x8f, 0xfb, 0xc6, 0x51, 0x57, 0x3f, 0x6c, 0x1d, 0xe8, 0x91, 0x3a, 0xbe, 0x0c, 0x05, 0x87,
|
0x32, 0xab, 0xd2, 0xec, 0x15, 0x28, 0x4e, 0x88, 0xa3, 0x52, 0xcb, 0x77, 0x2f, 0x78, 0x75, 0x59,
|
||||||
0x7c, 0x79, 0x9e, 0xad, 0xf5, 0x02, 0xba, 0x68, 0xf8, 0x2f, 0x43, 0xe1, 0x05, 0x25, 0xcf, 0xb2,
|
0x50, 0x0a, 0x13, 0xe2, 0xc8, 0xac, 0xfd, 0x42, 0x8a, 0xfc, 0x93, 0x6c, 0xa1, 0x80, 0x8a, 0x27,
|
||||||
0x15, 0x56, 0x40, 0xdf, 0xe1, 0x31, 0xb8, 0x03, 0x45, 0x11, 0x2f, 0x0c, 0x10, 0x45, 0x0c, 0xbd,
|
0xd9, 0x42, 0x11, 0x41, 0xf5, 0x5f, 0x19, 0x28, 0xc7, 0xab, 0x4d, 0x56, 0xbc, 0x6b, 0xfc, 0x64,
|
||||||
0x81, 0xcb, 0x50, 0xd8, 0xeb, 0xea, 0xfc, 0x28, 0x20, 0xa8, 0x49, 0xd4, 0xe8, 0x75, 0xb4, 0x3d,
|
0x49, 0xf1, 0xbd, 0xe7, 0x8d, 0xef, 0xad, 0x4d, 0x6b, 0x0d, 0x76, 0xe4, 0x1c, 0xe6, 0x45, 0x0d,
|
||||||
0x0d, 0xe5, 0x1a, 0xf7, 0xa1, 0x24, 0x83, 0xc0, 0x8f, 0x49, 0x12, 0x06, 0xf4, 0x46, 0x34, 0x8c,
|
0xa8, 0x08, 0x4d, 0x76, 0xdc, 0xb3, 0xdd, 0x86, 0x8a, 0x7b, 0x4d, 0x41, 0x09, 0x5a, 0xf8, 0x18,
|
||||||
0x6c, 0x28, 0xb1, 0xf4, 0xe4, 0x70, 0x57, 0xd3, 0x51, 0x2e, 0xbb, 0xc9, 0x05, 0x54, 0x6c, 0x04,
|
0xf2, 0x0f, 0x3d, 0x6e, 0x3b, 0xcf, 0x6d, 0xbf, 0xf9, 0xfd, 0xb6, 0x4f, 0xfa, 0xdc, 0x78, 0xf1,
|
||||||
0x50, 0x4b, 0x77, 0x6f, 0xdf, 0x4b, 0x7e, 0x35, 0xfe, 0xa2, 0x40, 0x35, 0xd5, 0x8d, 0xf1, 0x3e,
|
0xa4, 0xaf, 0x76, 0xba, 0xca, 0x69, 0xbd, 0xad, 0x04, 0xea, 0xf8, 0x1a, 0x64, 0x4d, 0xf2, 0xd5,
|
||||||
0x80, 0x38, 0x8e, 0xfb, 0xc2, 0x20, 0x8e, 0x4d, 0x82, 0x28, 0x35, 0x40, 0x40, 0x2d, 0x8e, 0x5c,
|
0x45, 0xf2, 0x70, 0xe2, 0xd0, 0x65, 0x27, 0xe1, 0x1a, 0x64, 0x9f, 0x50, 0xf2, 0x28, 0x79, 0x24,
|
||||||
0x74, 0xeb, 0xbe, 0x17, 0xe7, 0xff, 0xa8, 0x00, 0x9a, 0xee, 0xe4, 0xa6, 0x1c, 0x54, 0x7e, 0x50,
|
0x70, 0xe8, 0x47, 0x5c, 0x0c, 0xfb, 0x90, 0xe3, 0xf1, 0xc2, 0x00, 0x41, 0xc4, 0xd0, 0x4b, 0xb8,
|
||||||
0x07, 0xff, 0xa0, 0x40, 0x3d, 0xdb, 0xbe, 0x4d, 0xb9, 0x77, 0xf5, 0x07, 0x75, 0xef, 0xf7, 0x0a,
|
0x00, 0xd9, 0x46, 0x57, 0x61, 0x0b, 0x02, 0x41, 0x59, 0xa0, 0x6a, 0xaf, 0x25, 0x37, 0x64, 0x94,
|
||||||
0x2c, 0x67, 0x9a, 0xb6, 0xff, 0x2b, 0xef, 0x7e, 0x97, 0x87, 0xb5, 0x39, 0x7a, 0xb8, 0x15, 0x75,
|
0xae, 0xde, 0x85, 0xbc, 0x08, 0x02, 0x5b, 0x2c, 0x51, 0x18, 0xd0, 0x4b, 0x41, 0x33, 0xb0, 0x91,
|
||||||
0xb7, 0xb2, 0xe1, 0xfe, 0xf1, 0x45, 0xe6, 0x6a, 0xf2, 0xfb, 0xb3, 0x47, 0xfc, 0x30, 0x6a, 0x86,
|
0x0a, 0xa5, 0x67, 0xa7, 0x47, 0xb2, 0x82, 0xd2, 0xc9, 0xa9, 0xce, 0xa2, 0x5c, 0xd5, 0x83, 0x72,
|
||||||
0x6f, 0x02, 0xb2, 0x2d, 0xca, 0x42, 0x7b, 0x60, 0x53, 0x3f, 0xfa, 0x22, 0x97, 0x2d, 0xef, 0xca,
|
0xbc, 0xdc, 0x7c, 0x31, 0x57, 0xc9, 0xbf, 0xa7, 0xa0, 0x14, 0x2b, 0x1f, 0x59, 0xe1, 0x42, 0x4c,
|
||||||
0x04, 0x97, 0x1f, 0xe5, 0x3f, 0x02, 0xec, 0xb9, 0x81, 0x1d, 0xda, 0xcf, 0xa9, 0x61, 0xb3, 0xf8,
|
0xd3, 0x7e, 0xa2, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43, 0x2e, 0x3b, 0x75,
|
||||||
0xf3, 0x9d, 0xb7, 0xc0, 0x05, 0x1d, 0xc5, 0x92, 0x0e, 0x0b, 0x13, 0x36, 0xa3, 0x43, 0x32, 0xc5,
|
0x2f, 0x68, 0x89, 0xe4, 0x50, 0xbe, 0xfa, 0x97, 0x14, 0xa0, 0xf9, 0x02, 0x74, 0xce, 0xcd, 0xd4,
|
||||||
0xe6, 0x15, 0x30, 0xaf, 0xa3, 0x58, 0x92, 0xb0, 0xaf, 0x42, 0xcd, 0x72, 0xc7, 0xbc, 0xa1, 0x90,
|
0x4f, 0xe9, 0x66, 0xf5, 0xcf, 0x29, 0xa8, 0x24, 0xab, 0xce, 0x39, 0xf7, 0x6e, 0xfc, 0xa4, 0xee,
|
||||||
0x3c, 0x5e, 0x70, 0x15, 0xbd, 0x2a, 0xb1, 0x84, 0x12, 0x75, 0x7c, 0x93, 0x77, 0x83, 0x9a, 0x5e,
|
0xfd, 0x33, 0x0d, 0xeb, 0x89, 0x5a, 0xf3, 0xb2, 0xde, 0x7d, 0x09, 0x9b, 0x86, 0x4e, 0x27, 0x8e,
|
||||||
0x95, 0x98, 0xa4, 0xdc, 0x80, 0x15, 0x32, 0x1c, 0xfa, 0xdc, 0x78, 0x6c, 0x48, 0xf6, 0xb0, 0xf5,
|
0xed, 0x53, 0x4b, 0xbb, 0x50, 0x4d, 0xfa, 0x98, 0x9a, 0x52, 0x95, 0x6f, 0x1a, 0xfb, 0xdf, 0x5f,
|
||||||
0x04, 0x16, 0xc4, 0x8d, 0xc7, 0x50, 0x8e, 0xe3, 0xc0, 0x6f, 0x36, 0x1e, 0x09, 0xc3, 0x93, 0xaf,
|
0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0xd3, 0x5e, 0x77, 0x20,
|
||||||
0x37, 0xb9, 0xad, 0x8a, 0x5e, 0x66, 0xb1, 0xf0, 0x2a, 0xd4, 0xec, 0xc0, 0x98, 0x3c, 0x23, 0xe6,
|
0x77, 0x1a, 0x9f, 0xab, 0x67, 0x9d, 0x5f, 0x75, 0xba, 0x9f, 0x76, 0x14, 0x64, 0xcc, 0xd1, 0x7e,
|
||||||
0x36, 0x73, 0x5b, 0x65, 0xbd, 0x6a, 0x07, 0xc9, 0xbb, 0x51, 0xe3, 0xeb, 0x1c, 0xd4, 0xb3, 0xcf,
|
0xc4, 0x65, 0xdf, 0x03, 0x34, 0xef, 0x14, 0xbe, 0x0a, 0xcb, 0xdc, 0x42, 0x2f, 0xe1, 0x2d, 0xd8,
|
||||||
0xa0, 0xb8, 0x0d, 0x65, 0xc7, 0x35, 0x89, 0x48, 0x04, 0xf9, 0x06, 0xbf, 0xf5, 0x9a, 0x97, 0xd3,
|
0xe8, 0x74, 0xd5, 0x7e, 0xab, 0x29, 0xab, 0xf2, 0x83, 0x07, 0x72, 0x63, 0xd0, 0x17, 0xd7, 0xfb,
|
||||||
0xe6, 0x41, 0xc4, 0xd7, 0x13, 0xcd, 0x8d, 0xbf, 0x29, 0x50, 0x8e, 0x61, 0x7c, 0x09, 0x0a, 0x1e,
|
0x88, 0x3d, 0x48, 0x2c, 0xf0, 0xea, 0x9f, 0x32, 0xb0, 0xb5, 0xc4, 0x13, 0x5c, 0x0f, 0x6e, 0x16,
|
||||||
0x09, 0xcf, 0x84, 0xb9, 0xe2, 0x6e, 0x0e, 0x29, 0xba, 0x18, 0x73, 0x3c, 0xf0, 0x08, 0x13, 0x29,
|
0xe2, 0xb2, 0xf3, 0xee, 0x65, 0xbc, 0xaf, 0xb1, 0x82, 0xa0, 0x47, 0x5c, 0x3f, 0xb8, 0x88, 0xdc,
|
||||||
0x10, 0xe1, 0x7c, 0xcc, 0xf7, 0xd5, 0xa1, 0xc4, 0x12, 0x0d, 0xb2, 0x3b, 0x1a, 0x51, 0x16, 0x06,
|
0x02, 0x16, 0x25, 0xcb, 0x37, 0x86, 0x06, 0x75, 0x83, 0xd7, 0x10, 0x71, 0xdd, 0xd8, 0x98, 0xe1,
|
||||||
0xf1, 0xbe, 0x46, 0xf8, 0x5e, 0x04, 0xe3, 0xdb, 0xb0, 0x1a, 0xfa, 0xc4, 0x76, 0x32, 0xdc, 0x82,
|
0xe2, 0x41, 0xe4, 0x67, 0x80, 0x1d, 0xdb, 0x33, 0x7c, 0xe3, 0x31, 0x55, 0x0d, 0x2b, 0x7c, 0x3a,
|
||||||
0xe0, 0xa2, 0x58, 0x90, 0x90, 0x77, 0xe0, 0x72, 0x6c, 0xd7, 0xa2, 0x21, 0x31, 0xcf, 0xa8, 0x35,
|
0x61, 0xd7, 0x8f, 0xac, 0x82, 0x42, 0x49, 0xcb, 0xf2, 0x23, 0xb6, 0x45, 0x47, 0x64, 0x8e, 0xcd,
|
||||||
0x51, 0x2a, 0x89, 0x37, 0xb6, 0xb7, 0x22, 0x42, 0x3b, 0x92, 0xc7, 0xba, 0x8d, 0xbf, 0x2b, 0xb0,
|
0x36, 0xf3, 0x8c, 0x82, 0x42, 0x49, 0xc4, 0xbe, 0x01, 0x65, 0xdd, 0x9e, 0xb2, 0x9a, 0x4c, 0xf0,
|
||||||
0x1a, 0xb7, 0xf4, 0x56, 0x12, 0xac, 0x43, 0x00, 0xc2, 0x98, 0x1b, 0xa6, 0xc3, 0x35, 0x9b, 0xca,
|
0xd8, 0xd9, 0x91, 0x52, 0x4a, 0x02, 0x8b, 0x28, 0x41, 0xb5, 0x3d, 0x7b, 0xb3, 0x29, 0x2b, 0x25,
|
||||||
0x33, 0x7a, 0xcd, 0x56, 0xa2, 0xa4, 0xa7, 0x0c, 0x6c, 0x8c, 0x00, 0x26, 0x92, 0x85, 0x61, 0xbb,
|
0x81, 0x09, 0xca, 0x4d, 0xd8, 0x20, 0xa3, 0x91, 0xcb, 0x8c, 0x87, 0x86, 0xc4, 0xfd, 0xa1, 0x12,
|
||||||
0x02, 0xd5, 0xe8, 0x8d, 0x5b, 0xfc, 0xa3, 0x44, 0x7e, 0x04, 0x82, 0x84, 0x78, 0xef, 0x8f, 0xd7,
|
0xc1, 0x9c, 0xb8, 0x73, 0x02, 0x85, 0x30, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0x50, 0x1d, 0xf1, 0x6e,
|
||||||
0xa1, 0x78, 0x4a, 0x87, 0x36, 0x8b, 0x5e, 0xde, 0xe4, 0x20, 0x7e, 0xcf, 0x2b, 0x24, 0xef, 0x79,
|
0x97, 0xde, 0x2b, 0x2a, 0x05, 0x2b, 0x14, 0xde, 0x80, 0xb2, 0xe1, 0xa9, 0xb3, 0x27, 0xe8, 0xf4,
|
||||||
0xbb, 0x4f, 0x60, 0xcd, 0x74, 0x47, 0xd3, 0xee, 0xee, 0xa2, 0xa9, 0x0f, 0xd1, 0xe0, 0x33, 0xe5,
|
0x6e, 0x7a, 0xaf, 0xa0, 0x94, 0x0c, 0x2f, 0x7a, 0xbe, 0xab, 0x7e, 0x93, 0x86, 0x4a, 0xf2, 0x09,
|
||||||
0x0b, 0x98, 0x74, 0x6a, 0x5f, 0xe5, 0xf2, 0xfb, 0xbd, 0xdd, 0x3f, 0xe5, 0x36, 0xf6, 0xa5, 0x5e,
|
0x1d, 0x37, 0xa1, 0x60, 0xda, 0x1a, 0xe1, 0xa9, 0x25, 0xbe, 0xdf, 0xec, 0x3d, 0xe7, 0xd5, 0xbd,
|
||||||
0x2f, 0x5e, 0xa6, 0x4e, 0x07, 0x0e, 0x35, 0xb9, 0xeb, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x5f,
|
0xd6, 0x0e, 0xf8, 0x4a, 0xa4, 0xb9, 0xf3, 0x8f, 0x14, 0x14, 0x42, 0x18, 0x5f, 0x81, 0xac, 0x43,
|
||||||
0x1c, 0x48, 0x4f, 0x0d, 0x1a, 0x00, 0x00,
|
0xfc, 0x31, 0x37, 0x97, 0x3b, 0x4a, 0xa3, 0x94, 0xc2, 0xdb, 0x0c, 0xf7, 0x1c, 0x62, 0xf1, 0x14,
|
||||||
|
0x08, 0x70, 0xd6, 0x66, 0xf3, 0x6a, 0x52, 0xa2, 0xf3, 0xcb, 0x89, 0x3d, 0x99, 0x50, 0xcb, 0xf7,
|
||||||
|
0xc2, 0x79, 0x0d, 0xf0, 0x46, 0x00, 0xe3, 0x77, 0x60, 0xd3, 0x77, 0x89, 0x61, 0x26, 0xb8, 0x59,
|
||||||
|
0xce, 0x45, 0xa1, 0x20, 0x22, 0x1f, 0xc2, 0xb5, 0xd0, 0xae, 0x4e, 0x7d, 0xa2, 0x8d, 0xa9, 0x3e,
|
||||||
|
0x53, 0xca, 0xf3, 0xf7, 0xd9, 0xab, 0x01, 0xa1, 0x19, 0xc8, 0x43, 0xdd, 0xea, 0x77, 0x29, 0xd8,
|
||||||
|
0x0c, 0xaf, 0x53, 0x7a, 0x14, 0xac, 0x53, 0x00, 0x62, 0x59, 0xb6, 0x1f, 0x0f, 0xd7, 0x62, 0x2a,
|
||||||
|
0x2f, 0xe8, 0xd5, 0xea, 0x91, 0x92, 0x12, 0x33, 0xb0, 0x33, 0x01, 0x98, 0x49, 0x56, 0x86, 0xed,
|
||||||
|
0x3a, 0x94, 0x82, 0xef, 0x23, 0xfc, 0x23, 0x9b, 0xb8, 0x80, 0x83, 0x80, 0xd8, 0xbd, 0x0b, 0x6f,
|
||||||
|
0x43, 0xee, 0x9c, 0x8e, 0x0c, 0x2b, 0x78, 0xf5, 0x14, 0x8d, 0xf0, 0x25, 0x37, 0x1b, 0xbd, 0xe4,
|
||||||
|
0x1e, 0xfd, 0x21, 0x05, 0x5b, 0x9a, 0x3d, 0x99, 0xf7, 0xf7, 0x08, 0xcd, 0xbd, 0x02, 0x78, 0x9f,
|
||||||
|
0xa4, 0xbe, 0xf8, 0x78, 0x64, 0xf8, 0xe3, 0xe9, 0x79, 0x4d, 0xb3, 0x27, 0xfb, 0x23, 0xdb, 0x24,
|
||||||
|
0xd6, 0x68, 0xf6, 0x95, 0x90, 0xff, 0xd1, 0xde, 0x1d, 0x51, 0xeb, 0xdd, 0x91, 0x1d, 0xfb, 0x66,
|
||||||
|
0xf8, 0xd1, 0xec, 0xef, 0xd7, 0xe9, 0xcc, 0x71, 0xef, 0xe8, 0xaf, 0xe9, 0x9d, 0x63, 0xd1, 0x57,
|
||||||
|
0x2f, 0x8c, 0x8d, 0x42, 0x87, 0x26, 0xd5, 0xd8, 0x78, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x0c,
|
||||||
|
0xab, 0xb6, 0x37, 0x7e, 0x1c, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
849
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
generated
vendored
Normal file
849
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
generated
vendored
Normal file
|
@ -0,0 +1,849 @@
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// The messages in this file describe the definitions found in .proto files.
|
||||||
|
// A valid .proto file can be translated directly to a FileDescriptorProto
|
||||||
|
// without any other information (e.g. without reading its imports).
|
||||||
|
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "DescriptorProtos";
|
||||||
|
option csharp_namespace = "Google.Protobuf.Reflection";
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
|
||||||
|
// descriptor.proto must be optimized for speed because reflection-based
|
||||||
|
// algorithms don't work during bootstrapping.
|
||||||
|
option optimize_for = SPEED;
|
||||||
|
|
||||||
|
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
||||||
|
// files it parses.
|
||||||
|
message FileDescriptorSet {
|
||||||
|
repeated FileDescriptorProto file = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a complete .proto file.
|
||||||
|
message FileDescriptorProto {
|
||||||
|
optional string name = 1; // file name, relative to root of source tree
|
||||||
|
optional string package = 2; // e.g. "foo", "foo.bar", etc.
|
||||||
|
|
||||||
|
// Names of files imported by this file.
|
||||||
|
repeated string dependency = 3;
|
||||||
|
// Indexes of the public imported files in the dependency list above.
|
||||||
|
repeated int32 public_dependency = 10;
|
||||||
|
// Indexes of the weak imported files in the dependency list.
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
repeated int32 weak_dependency = 11;
|
||||||
|
|
||||||
|
// All top-level definitions in this file.
|
||||||
|
repeated DescriptorProto message_type = 4;
|
||||||
|
repeated EnumDescriptorProto enum_type = 5;
|
||||||
|
repeated ServiceDescriptorProto service = 6;
|
||||||
|
repeated FieldDescriptorProto extension = 7;
|
||||||
|
|
||||||
|
optional FileOptions options = 8;
|
||||||
|
|
||||||
|
// This field contains optional information about the original source code.
|
||||||
|
// You may safely remove this entire field without harming runtime
|
||||||
|
// functionality of the descriptors -- the information is needed only by
|
||||||
|
// development tools.
|
||||||
|
optional SourceCodeInfo source_code_info = 9;
|
||||||
|
|
||||||
|
// The syntax of the proto file.
|
||||||
|
// The supported values are "proto2" and "proto3".
|
||||||
|
optional string syntax = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a message type.
|
||||||
|
message DescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated FieldDescriptorProto field = 2;
|
||||||
|
repeated FieldDescriptorProto extension = 6;
|
||||||
|
|
||||||
|
repeated DescriptorProto nested_type = 3;
|
||||||
|
repeated EnumDescriptorProto enum_type = 4;
|
||||||
|
|
||||||
|
message ExtensionRange {
|
||||||
|
optional int32 start = 1;
|
||||||
|
optional int32 end = 2;
|
||||||
|
|
||||||
|
optional ExtensionRangeOptions options = 3;
|
||||||
|
}
|
||||||
|
repeated ExtensionRange extension_range = 5;
|
||||||
|
|
||||||
|
repeated OneofDescriptorProto oneof_decl = 8;
|
||||||
|
|
||||||
|
optional MessageOptions options = 7;
|
||||||
|
|
||||||
|
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
||||||
|
// fields or extension ranges in the same message. Reserved ranges may
|
||||||
|
// not overlap.
|
||||||
|
message ReservedRange {
|
||||||
|
optional int32 start = 1; // Inclusive.
|
||||||
|
optional int32 end = 2; // Exclusive.
|
||||||
|
}
|
||||||
|
repeated ReservedRange reserved_range = 9;
|
||||||
|
// Reserved field names, which may not be used by fields in the same message.
|
||||||
|
// A given name may only be reserved once.
|
||||||
|
repeated string reserved_name = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtensionRangeOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a field within a message.
|
||||||
|
message FieldDescriptorProto {
|
||||||
|
enum Type {
|
||||||
|
// 0 is reserved for errors.
|
||||||
|
// Order is weird for historical reasons.
|
||||||
|
TYPE_DOUBLE = 1;
|
||||||
|
TYPE_FLOAT = 2;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT64 = 3;
|
||||||
|
TYPE_UINT64 = 4;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT32 = 5;
|
||||||
|
TYPE_FIXED64 = 6;
|
||||||
|
TYPE_FIXED32 = 7;
|
||||||
|
TYPE_BOOL = 8;
|
||||||
|
TYPE_STRING = 9;
|
||||||
|
// Tag-delimited aggregate.
|
||||||
|
// Group type is deprecated and not supported in proto3. However, Proto3
|
||||||
|
// implementations should still be able to parse the group wire format and
|
||||||
|
// treat group fields as unknown fields.
|
||||||
|
TYPE_GROUP = 10;
|
||||||
|
TYPE_MESSAGE = 11; // Length-delimited aggregate.
|
||||||
|
|
||||||
|
// New in version 2.
|
||||||
|
TYPE_BYTES = 12;
|
||||||
|
TYPE_UINT32 = 13;
|
||||||
|
TYPE_ENUM = 14;
|
||||||
|
TYPE_SFIXED32 = 15;
|
||||||
|
TYPE_SFIXED64 = 16;
|
||||||
|
TYPE_SINT32 = 17; // Uses ZigZag encoding.
|
||||||
|
TYPE_SINT64 = 18; // Uses ZigZag encoding.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Label {
|
||||||
|
// 0 is reserved for errors
|
||||||
|
LABEL_OPTIONAL = 1;
|
||||||
|
LABEL_REQUIRED = 2;
|
||||||
|
LABEL_REPEATED = 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 3;
|
||||||
|
optional Label label = 4;
|
||||||
|
|
||||||
|
// If type_name is set, this need not be set. If both this and type_name
|
||||||
|
// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
|
||||||
|
optional Type type = 5;
|
||||||
|
|
||||||
|
// For message and enum types, this is the name of the type. If the name
|
||||||
|
// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
|
||||||
|
// rules are used to find the type (i.e. first the nested types within this
|
||||||
|
// message are searched, then within the parent, on up to the root
|
||||||
|
// namespace).
|
||||||
|
optional string type_name = 6;
|
||||||
|
|
||||||
|
// For extensions, this is the name of the type being extended. It is
|
||||||
|
// resolved in the same manner as type_name.
|
||||||
|
optional string extendee = 2;
|
||||||
|
|
||||||
|
// For numeric types, contains the original text representation of the value.
|
||||||
|
// For booleans, "true" or "false".
|
||||||
|
// For strings, contains the default text contents (not escaped in any way).
|
||||||
|
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
|
||||||
|
// TODO(kenton): Base-64 encode?
|
||||||
|
optional string default_value = 7;
|
||||||
|
|
||||||
|
// If set, gives the index of a oneof in the containing type's oneof_decl
|
||||||
|
// list. This field is a member of that oneof.
|
||||||
|
optional int32 oneof_index = 9;
|
||||||
|
|
||||||
|
// JSON name of this field. The value is set by protocol compiler. If the
|
||||||
|
// user has set a "json_name" option on this field, that option's value
|
||||||
|
// will be used. Otherwise, it's deduced from the field's name by converting
|
||||||
|
// it to camelCase.
|
||||||
|
optional string json_name = 10;
|
||||||
|
|
||||||
|
optional FieldOptions options = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a oneof.
|
||||||
|
message OneofDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
optional OneofOptions options = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes an enum type.
|
||||||
|
message EnumDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated EnumValueDescriptorProto value = 2;
|
||||||
|
|
||||||
|
optional EnumOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a value within an enum.
|
||||||
|
message EnumValueDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 2;
|
||||||
|
|
||||||
|
optional EnumValueOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a service.
|
||||||
|
message ServiceDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
repeated MethodDescriptorProto method = 2;
|
||||||
|
|
||||||
|
optional ServiceOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a method of a service.
|
||||||
|
message MethodDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
// Input and output type names. These are resolved in the same way as
|
||||||
|
// FieldDescriptorProto.type_name, but must refer to a message type.
|
||||||
|
optional string input_type = 2;
|
||||||
|
optional string output_type = 3;
|
||||||
|
|
||||||
|
optional MethodOptions options = 4;
|
||||||
|
|
||||||
|
// Identifies if client streams multiple client messages
|
||||||
|
optional bool client_streaming = 5 [default=false];
|
||||||
|
// Identifies if server streams multiple server messages
|
||||||
|
optional bool server_streaming = 6 [default=false];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Options
|
||||||
|
|
||||||
|
// Each of the definitions above may have "options" attached. These are
|
||||||
|
// just annotations which may cause code to be generated slightly differently
|
||||||
|
// or may contain hints for code that manipulates protocol messages.
|
||||||
|
//
|
||||||
|
// Clients may define custom options as extensions of the *Options messages.
|
||||||
|
// These extensions may not yet be known at parsing time, so the parser cannot
|
||||||
|
// store the values in them. Instead it stores them in a field in the *Options
|
||||||
|
// message called uninterpreted_option. This field must have the same name
|
||||||
|
// across all *Options messages. We then use this field to populate the
|
||||||
|
// extensions when we build a descriptor, at which point all protos have been
|
||||||
|
// parsed and so all extensions are known.
|
||||||
|
//
|
||||||
|
// Extension numbers for custom options may be chosen as follows:
|
||||||
|
// * For options which will only be used within a single application or
|
||||||
|
// organization, or for experimental options, use field numbers 50000
|
||||||
|
// through 99999. It is up to you to ensure that you do not use the
|
||||||
|
// same number for multiple options.
|
||||||
|
// * For options which will be published and used publicly by multiple
|
||||||
|
// independent entities, e-mail protobuf-global-extension-registry@google.com
|
||||||
|
// to reserve extension numbers. Simply provide your project name (e.g.
|
||||||
|
// Objective-C plugin) and your project website (if available) -- there's no
|
||||||
|
// need to explain how you intend to use them. Usually you only need one
|
||||||
|
// extension number. You can declare multiple options with only one extension
|
||||||
|
// number by putting them in a sub-message. See the Custom Options section of
|
||||||
|
// the docs for examples:
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto#options
|
||||||
|
// If this turns out to be popular, a web service will be set up
|
||||||
|
// to automatically assign option numbers.
|
||||||
|
|
||||||
|
|
||||||
|
message FileOptions {
|
||||||
|
|
||||||
|
// Sets the Java package where classes generated from this .proto will be
|
||||||
|
// placed. By default, the proto package is used, but this is often
|
||||||
|
// inappropriate because proto packages do not normally start with backwards
|
||||||
|
// domain names.
|
||||||
|
optional string java_package = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// If set, all the classes from the .proto file are wrapped in a single
|
||||||
|
// outer class with the given name. This applies to both Proto1
|
||||||
|
// (equivalent to the old "--one_java_file" option) and Proto2 (where
|
||||||
|
// a .proto always translates to a single class, but you may want to
|
||||||
|
// explicitly choose the class name).
|
||||||
|
optional string java_outer_classname = 8;
|
||||||
|
|
||||||
|
// If set true, then the Java code generator will generate a separate .java
|
||||||
|
// file for each top-level message, enum, and service defined in the .proto
|
||||||
|
// file. Thus, these types will *not* be nested inside the outer class
|
||||||
|
// named by java_outer_classname. However, the outer class will still be
|
||||||
|
// generated to contain the file's getDescriptor() method as well as any
|
||||||
|
// top-level extensions defined in the file.
|
||||||
|
optional bool java_multiple_files = 10 [default=false];
|
||||||
|
|
||||||
|
// This option does nothing.
|
||||||
|
optional bool java_generate_equals_and_hash = 20 [deprecated=true];
|
||||||
|
|
||||||
|
// If set true, then the Java2 code generator will generate code that
|
||||||
|
// throws an exception whenever an attempt is made to assign a non-UTF-8
|
||||||
|
// byte sequence to a string field.
|
||||||
|
// Message reflection will do the same.
|
||||||
|
// However, an extension field still accepts non-UTF-8 byte sequences.
|
||||||
|
// This option has no effect on when used with the lite runtime.
|
||||||
|
optional bool java_string_check_utf8 = 27 [default=false];
|
||||||
|
|
||||||
|
|
||||||
|
// Generated classes can be optimized for speed or code size.
|
||||||
|
enum OptimizeMode {
|
||||||
|
SPEED = 1; // Generate complete code for parsing, serialization,
|
||||||
|
// etc.
|
||||||
|
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
|
||||||
|
LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
|
||||||
|
}
|
||||||
|
optional OptimizeMode optimize_for = 9 [default=SPEED];
|
||||||
|
|
||||||
|
// Sets the Go package where structs generated from this .proto will be
|
||||||
|
// placed. If omitted, the Go package will be derived from the following:
|
||||||
|
// - The basename of the package import path, if provided.
|
||||||
|
// - Otherwise, the package statement in the .proto file, if present.
|
||||||
|
// - Otherwise, the basename of the .proto file, without extension.
|
||||||
|
optional string go_package = 11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should generic services be generated in each language? "Generic" services
|
||||||
|
// are not specific to any particular RPC system. They are generated by the
|
||||||
|
// main code generators in each language (without additional plugins).
|
||||||
|
// Generic services were the only kind of service generation supported by
|
||||||
|
// early versions of google.protobuf.
|
||||||
|
//
|
||||||
|
// Generic services are now considered deprecated in favor of using plugins
|
||||||
|
// that generate code specific to your particular RPC system. Therefore,
|
||||||
|
// these default to false. Old code which depends on generic services should
|
||||||
|
// explicitly set them to true.
|
||||||
|
optional bool cc_generic_services = 16 [default=false];
|
||||||
|
optional bool java_generic_services = 17 [default=false];
|
||||||
|
optional bool py_generic_services = 18 [default=false];
|
||||||
|
optional bool php_generic_services = 42 [default=false];
|
||||||
|
|
||||||
|
// Is this file deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for everything in the file, or it will be completely ignored; in the very
|
||||||
|
// least, this is a formalization for deprecating files.
|
||||||
|
optional bool deprecated = 23 [default=false];
|
||||||
|
|
||||||
|
// Enables the use of arenas for the proto messages in this file. This applies
|
||||||
|
// only to generated classes for C++.
|
||||||
|
optional bool cc_enable_arenas = 31 [default=false];
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the objective c class prefix which is prepended to all objective c
|
||||||
|
// generated classes from this .proto. There is no default.
|
||||||
|
optional string objc_class_prefix = 36;
|
||||||
|
|
||||||
|
// Namespace for generated classes; defaults to the package.
|
||||||
|
optional string csharp_namespace = 37;
|
||||||
|
|
||||||
|
// By default Swift generators will take the proto package and CamelCase it
|
||||||
|
// replacing '.' with underscore and use that to prefix the types/symbols
|
||||||
|
// defined. When this options is provided, they will use this value instead
|
||||||
|
// to prefix the types/symbols defined.
|
||||||
|
optional string swift_prefix = 39;
|
||||||
|
|
||||||
|
// Sets the php class prefix which is prepended to all php generated classes
|
||||||
|
// from this .proto. Default is empty.
|
||||||
|
optional string php_class_prefix = 40;
|
||||||
|
|
||||||
|
// Use this option to change the namespace of php generated classes. Default
|
||||||
|
// is empty. When this option is empty, the package name will be used for
|
||||||
|
// determining the namespace.
|
||||||
|
optional string php_namespace = 41;
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
|
||||||
|
reserved 38;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageOptions {
|
||||||
|
// Set true to use the old proto1 MessageSet wire format for extensions.
|
||||||
|
// This is provided for backwards-compatibility with the MessageSet wire
|
||||||
|
// format. You should not use this for any other reason: It's less
|
||||||
|
// efficient, has fewer features, and is more complicated.
|
||||||
|
//
|
||||||
|
// The message must be defined exactly as follows:
|
||||||
|
// message Foo {
|
||||||
|
// option message_set_wire_format = true;
|
||||||
|
// extensions 4 to max;
|
||||||
|
// }
|
||||||
|
// Note that the message cannot have any defined fields; MessageSets only
|
||||||
|
// have extensions.
|
||||||
|
//
|
||||||
|
// All extensions of your type must be singular messages; e.g. they cannot
|
||||||
|
// be int32s, enums, or repeated messages.
|
||||||
|
//
|
||||||
|
// Because this is an option, the above two restrictions are not enforced by
|
||||||
|
// the protocol compiler.
|
||||||
|
optional bool message_set_wire_format = 1 [default=false];
|
||||||
|
|
||||||
|
// Disables the generation of the standard "descriptor()" accessor, which can
|
||||||
|
// conflict with a field of the same name. This is meant to make migration
|
||||||
|
// from proto1 easier; new code should avoid fields named "descriptor".
|
||||||
|
optional bool no_standard_descriptor_accessor = 2 [default=false];
|
||||||
|
|
||||||
|
// Is this message deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the message, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating messages.
|
||||||
|
optional bool deprecated = 3 [default=false];
|
||||||
|
|
||||||
|
// Whether the message is an automatically generated map entry type for the
|
||||||
|
// maps field.
|
||||||
|
//
|
||||||
|
// For maps fields:
|
||||||
|
// map<KeyType, ValueType> map_field = 1;
|
||||||
|
// The parsed descriptor looks like:
|
||||||
|
// message MapFieldEntry {
|
||||||
|
// option map_entry = true;
|
||||||
|
// optional KeyType key = 1;
|
||||||
|
// optional ValueType value = 2;
|
||||||
|
// }
|
||||||
|
// repeated MapFieldEntry map_field = 1;
|
||||||
|
//
|
||||||
|
// Implementations may choose not to generate the map_entry=true message, but
|
||||||
|
// use a native map in the target language to hold the keys and values.
|
||||||
|
// The reflection APIs in such implementions still need to work as
|
||||||
|
// if the field is a repeated message field.
|
||||||
|
//
|
||||||
|
// NOTE: Do not set the option in .proto files. Always use the maps syntax
|
||||||
|
// instead. The option should only be implicitly set by the proto compiler
|
||||||
|
// parser.
|
||||||
|
optional bool map_entry = 7;
|
||||||
|
|
||||||
|
reserved 8; // javalite_serializable
|
||||||
|
reserved 9; // javanano_as_lite
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FieldOptions {
|
||||||
|
// The ctype option instructs the C++ code generator to use a different
|
||||||
|
// representation of the field than it normally would. See the specific
|
||||||
|
// options below. This option is not yet implemented in the open source
|
||||||
|
// release -- sorry, we'll try to include it in a future version!
|
||||||
|
optional CType ctype = 1 [default = STRING];
|
||||||
|
enum CType {
|
||||||
|
// Default mode.
|
||||||
|
STRING = 0;
|
||||||
|
|
||||||
|
CORD = 1;
|
||||||
|
|
||||||
|
STRING_PIECE = 2;
|
||||||
|
}
|
||||||
|
// The packed option can be enabled for repeated primitive fields to enable
|
||||||
|
// a more efficient representation on the wire. Rather than repeatedly
|
||||||
|
// writing the tag and type for each element, the entire array is encoded as
|
||||||
|
// a single length-delimited blob. In proto3, only explicit setting it to
|
||||||
|
// false will avoid using packed encoding.
|
||||||
|
optional bool packed = 2;
|
||||||
|
|
||||||
|
// The jstype option determines the JavaScript type used for values of the
|
||||||
|
// field. The option is permitted only for 64 bit integral and fixed types
|
||||||
|
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
|
||||||
|
// is represented as JavaScript string, which avoids loss of precision that
|
||||||
|
// can happen when a large value is converted to a floating point JavaScript.
|
||||||
|
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
|
||||||
|
// use the JavaScript "number" type. The behavior of the default option
|
||||||
|
// JS_NORMAL is implementation dependent.
|
||||||
|
//
|
||||||
|
// This option is an enum to permit additional types to be added, e.g.
|
||||||
|
// goog.math.Integer.
|
||||||
|
optional JSType jstype = 6 [default = JS_NORMAL];
|
||||||
|
enum JSType {
|
||||||
|
// Use the default type.
|
||||||
|
JS_NORMAL = 0;
|
||||||
|
|
||||||
|
// Use JavaScript strings.
|
||||||
|
JS_STRING = 1;
|
||||||
|
|
||||||
|
// Use JavaScript numbers.
|
||||||
|
JS_NUMBER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
|
// inner message's contents will not be parsed but instead stored in encoded
|
||||||
|
// form. The inner message will actually be parsed when it is first accessed.
|
||||||
|
//
|
||||||
|
// This is only a hint. Implementations are free to choose whether to use
|
||||||
|
// eager or lazy parsing regardless of the value of this option. However,
|
||||||
|
// setting this option true suggests that the protocol author believes that
|
||||||
|
// using lazy parsing on this field is worth the additional bookkeeping
|
||||||
|
// overhead typically needed to implement it.
|
||||||
|
//
|
||||||
|
// This option does not affect the public interface of any generated code;
|
||||||
|
// all method signatures remain the same. Furthermore, thread-safety of the
|
||||||
|
// interface is not affected by this option; const methods remain safe to
|
||||||
|
// call from multiple threads concurrently, while non-const methods continue
|
||||||
|
// to require exclusive access.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Note that implementations may choose not to check required fields within
|
||||||
|
// a lazy sub-message. That is, calling IsInitialized() on the outer message
|
||||||
|
// may return true even if the inner message has missing required fields.
|
||||||
|
// This is necessary because otherwise the inner message would have to be
|
||||||
|
// parsed in order to perform the check, defeating the purpose of lazy
|
||||||
|
// parsing. An implementation which chooses not to check required fields
|
||||||
|
// must be consistent about it. That is, for any particular sub-message, the
|
||||||
|
// implementation must either *always* check its required fields, or *never*
|
||||||
|
// check its required fields, regardless of whether or not the message has
|
||||||
|
// been parsed.
|
||||||
|
optional bool lazy = 5 [default=false];
|
||||||
|
|
||||||
|
// Is this field deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for accessors, or it will be completely ignored; in the very least, this
|
||||||
|
// is a formalization for deprecating fields.
|
||||||
|
optional bool deprecated = 3 [default=false];
|
||||||
|
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
optional bool weak = 10 [default=false];
|
||||||
|
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
|
||||||
|
reserved 4; // removed jtype
|
||||||
|
}
|
||||||
|
|
||||||
|
message OneofOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumOptions {
|
||||||
|
|
||||||
|
// Set this option to true to allow mapping different tag names to the same
|
||||||
|
// value.
|
||||||
|
optional bool allow_alias = 2;
|
||||||
|
|
||||||
|
// Is this enum deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the enum, or it will be completely ignored; in the very least, this
|
||||||
|
// is a formalization for deprecating enums.
|
||||||
|
optional bool deprecated = 3 [default=false];
|
||||||
|
|
||||||
|
reserved 5; // javanano_as_lite
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumValueOptions {
|
||||||
|
// Is this enum value deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the enum value, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating enum values.
|
||||||
|
optional bool deprecated = 1 [default=false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServiceOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// Is this service deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the service, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating services.
|
||||||
|
optional bool deprecated = 33 [default=false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MethodOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// Is this method deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the method, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating methods.
|
||||||
|
optional bool deprecated = 33 [default=false];
|
||||||
|
|
||||||
|
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
|
||||||
|
// or neither? HTTP based RPC implementation may choose GET verb for safe
|
||||||
|
// methods, and PUT verb for idempotent methods instead of the default POST.
|
||||||
|
enum IdempotencyLevel {
|
||||||
|
IDEMPOTENCY_UNKNOWN = 0;
|
||||||
|
NO_SIDE_EFFECTS = 1; // implies idempotent
|
||||||
|
IDEMPOTENT = 2; // idempotent, but may have side effects
|
||||||
|
}
|
||||||
|
optional IdempotencyLevel idempotency_level =
|
||||||
|
34 [default=IDEMPOTENCY_UNKNOWN];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A message representing a option the parser does not recognize. This only
|
||||||
|
// appears in options protos created by the compiler::Parser class.
|
||||||
|
// DescriptorPool resolves these when building Descriptor objects. Therefore,
|
||||||
|
// options protos in descriptor objects (e.g. returned by Descriptor::options(),
|
||||||
|
// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
|
||||||
|
// in them.
|
||||||
|
message UninterpretedOption {
|
||||||
|
// The name of the uninterpreted option. Each string represents a segment in
|
||||||
|
// a dot-separated name. is_extension is true iff a segment represents an
|
||||||
|
// extension (denoted with parentheses in options specs in .proto files).
|
||||||
|
// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
|
||||||
|
// "foo.(bar.baz).qux".
|
||||||
|
message NamePart {
|
||||||
|
required string name_part = 1;
|
||||||
|
required bool is_extension = 2;
|
||||||
|
}
|
||||||
|
repeated NamePart name = 2;
|
||||||
|
|
||||||
|
// The value of the uninterpreted option, in whatever type the tokenizer
|
||||||
|
// identified it as during parsing. Exactly one of these should be set.
|
||||||
|
optional string identifier_value = 3;
|
||||||
|
optional uint64 positive_int_value = 4;
|
||||||
|
optional int64 negative_int_value = 5;
|
||||||
|
optional double double_value = 6;
|
||||||
|
optional bytes string_value = 7;
|
||||||
|
optional string aggregate_value = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Optional source code info
|
||||||
|
|
||||||
|
// Encapsulates information about the original source file from which a
|
||||||
|
// FileDescriptorProto was generated.
|
||||||
|
message SourceCodeInfo {
|
||||||
|
// A Location identifies a piece of source code in a .proto file which
|
||||||
|
// corresponds to a particular definition. This information is intended
|
||||||
|
// to be useful to IDEs, code indexers, documentation generators, and similar
|
||||||
|
// tools.
|
||||||
|
//
|
||||||
|
// For example, say we have a file like:
|
||||||
|
// message Foo {
|
||||||
|
// optional string foo = 1;
|
||||||
|
// }
|
||||||
|
// Let's look at just the field definition:
|
||||||
|
// optional string foo = 1;
|
||||||
|
// ^ ^^ ^^ ^ ^^^
|
||||||
|
// a bc de f ghi
|
||||||
|
// We have the following locations:
|
||||||
|
// span path represents
|
||||||
|
// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
|
||||||
|
// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
|
||||||
|
// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
|
||||||
|
// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
|
||||||
|
// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - A location may refer to a repeated field itself (i.e. not to any
|
||||||
|
// particular index within it). This is used whenever a set of elements are
|
||||||
|
// logically enclosed in a single code segment. For example, an entire
|
||||||
|
// extend block (possibly containing multiple extension definitions) will
|
||||||
|
// have an outer location whose path refers to the "extensions" repeated
|
||||||
|
// field without an index.
|
||||||
|
// - Multiple locations may have the same path. This happens when a single
|
||||||
|
// logical declaration is spread out across multiple places. The most
|
||||||
|
// obvious example is the "extend" block again -- there may be multiple
|
||||||
|
// extend blocks in the same scope, each of which will have the same path.
|
||||||
|
// - A location's span is not always a subset of its parent's span. For
|
||||||
|
// example, the "extendee" of an extension declaration appears at the
|
||||||
|
// beginning of the "extend" block and is shared by all extensions within
|
||||||
|
// the block.
|
||||||
|
// - Just because a location's span is a subset of some other location's span
|
||||||
|
// does not mean that it is a descendent. For example, a "group" defines
|
||||||
|
// both a type and a field in a single declaration. Thus, the locations
|
||||||
|
// corresponding to the type and field and their components will overlap.
|
||||||
|
// - Code which tries to interpret locations should probably be designed to
|
||||||
|
// ignore those that it doesn't understand, as more types of locations could
|
||||||
|
// be recorded in the future.
|
||||||
|
repeated Location location = 1;
|
||||||
|
message Location {
|
||||||
|
// Identifies which part of the FileDescriptorProto was defined at this
|
||||||
|
// location.
|
||||||
|
//
|
||||||
|
// Each element is a field number or an index. They form a path from
|
||||||
|
// the root FileDescriptorProto to the place where the definition. For
|
||||||
|
// example, this path:
|
||||||
|
// [ 4, 3, 2, 7, 1 ]
|
||||||
|
// refers to:
|
||||||
|
// file.message_type(3) // 4, 3
|
||||||
|
// .field(7) // 2, 7
|
||||||
|
// .name() // 1
|
||||||
|
// This is because FileDescriptorProto.message_type has field number 4:
|
||||||
|
// repeated DescriptorProto message_type = 4;
|
||||||
|
// and DescriptorProto.field has field number 2:
|
||||||
|
// repeated FieldDescriptorProto field = 2;
|
||||||
|
// and FieldDescriptorProto.name has field number 1:
|
||||||
|
// optional string name = 1;
|
||||||
|
//
|
||||||
|
// Thus, the above path gives the location of a field name. If we removed
|
||||||
|
// the last element:
|
||||||
|
// [ 4, 3, 2, 7 ]
|
||||||
|
// this path refers to the whole field declaration (from the beginning
|
||||||
|
// of the label to the terminating semicolon).
|
||||||
|
repeated int32 path = 1 [packed=true];
|
||||||
|
|
||||||
|
// Always has exactly three or four elements: start line, start column,
|
||||||
|
// end line (optional, otherwise assumed same as start line), end column.
|
||||||
|
// These are packed into a single field for efficiency. Note that line
|
||||||
|
// and column numbers are zero-based -- typically you will want to add
|
||||||
|
// 1 to each before displaying to a user.
|
||||||
|
repeated int32 span = 2 [packed=true];
|
||||||
|
|
||||||
|
// If this SourceCodeInfo represents a complete declaration, these are any
|
||||||
|
// comments appearing before and after the declaration which appear to be
|
||||||
|
// attached to the declaration.
|
||||||
|
//
|
||||||
|
// A series of line comments appearing on consecutive lines, with no other
|
||||||
|
// tokens appearing on those lines, will be treated as a single comment.
|
||||||
|
//
|
||||||
|
// leading_detached_comments will keep paragraphs of comments that appear
|
||||||
|
// before (but not connected to) the current element. Each paragraph,
|
||||||
|
// separated by empty lines, will be one comment element in the repeated
|
||||||
|
// field.
|
||||||
|
//
|
||||||
|
// Only the comment content is provided; comment markers (e.g. //) are
|
||||||
|
// stripped out. For block comments, leading whitespace and an asterisk
|
||||||
|
// will be stripped from the beginning of each line other than the first.
|
||||||
|
// Newlines are included in the output.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// optional int32 foo = 1; // Comment attached to foo.
|
||||||
|
// // Comment attached to bar.
|
||||||
|
// optional int32 bar = 2;
|
||||||
|
//
|
||||||
|
// optional string baz = 3;
|
||||||
|
// // Comment attached to baz.
|
||||||
|
// // Another line attached to baz.
|
||||||
|
//
|
||||||
|
// // Comment attached to qux.
|
||||||
|
// //
|
||||||
|
// // Another line attached to qux.
|
||||||
|
// optional double qux = 4;
|
||||||
|
//
|
||||||
|
// // Detached comment for corge. This is not leading or trailing comments
|
||||||
|
// // to qux or corge because there are blank lines separating it from
|
||||||
|
// // both.
|
||||||
|
//
|
||||||
|
// // Detached comment for corge paragraph 2.
|
||||||
|
//
|
||||||
|
// optional string corge = 5;
|
||||||
|
// /* Block comment attached
|
||||||
|
// * to corge. Leading asterisks
|
||||||
|
// * will be removed. */
|
||||||
|
// /* Block comment attached to
|
||||||
|
// * grault. */
|
||||||
|
// optional int32 grault = 6;
|
||||||
|
//
|
||||||
|
// // ignored detached comments.
|
||||||
|
optional string leading_comments = 3;
|
||||||
|
optional string trailing_comments = 4;
|
||||||
|
repeated string leading_detached_comments = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes the relationship between generated code and its original source
|
||||||
|
// file. A GeneratedCodeInfo message is associated with only one generated
|
||||||
|
// source file, but may contain references to different source .proto files.
|
||||||
|
message GeneratedCodeInfo {
|
||||||
|
// An Annotation connects some span of text in generated code to an element
|
||||||
|
// of its generating .proto file.
|
||||||
|
repeated Annotation annotation = 1;
|
||||||
|
message Annotation {
|
||||||
|
// Identifies the element in the original source .proto file. This field
|
||||||
|
// is formatted the same as SourceCodeInfo.Location.path.
|
||||||
|
repeated int32 path = 1 [packed=true];
|
||||||
|
|
||||||
|
// Identifies the filesystem path to the original source .proto.
|
||||||
|
optional string source_file = 2;
|
||||||
|
|
||||||
|
// Identifies the starting offset in bytes in the generated code
|
||||||
|
// that relates to the identified object.
|
||||||
|
optional int32 begin = 3;
|
||||||
|
|
||||||
|
// Identifies the ending offset in bytes in the generated code that
|
||||||
|
// relates to the identified offset. The end offset should be one past
|
||||||
|
// the last relevant byte (so the length of the text = end - begin).
|
||||||
|
optional int32 end = 4;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
// 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 ptypes
|
||||||
|
|
||||||
|
// This file implements functions to marshal proto.Message to/from
|
||||||
|
// google.protobuf.Any message.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
|
)
|
||||||
|
|
||||||
|
const googleApis = "type.googleapis.com/"
|
||||||
|
|
||||||
|
// AnyMessageName returns the name of the message contained in a google.protobuf.Any message.
|
||||||
|
//
|
||||||
|
// Note that regular type assertions should be done using the Is
|
||||||
|
// function. AnyMessageName is provided for less common use cases like filtering a
|
||||||
|
// sequence of Any messages based on a set of allowed message type names.
|
||||||
|
func AnyMessageName(any *any.Any) (string, error) {
|
||||||
|
if any == nil {
|
||||||
|
return "", fmt.Errorf("message is nil")
|
||||||
|
}
|
||||||
|
slash := strings.LastIndex(any.TypeUrl, "/")
|
||||||
|
if slash < 0 {
|
||||||
|
return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
|
||||||
|
}
|
||||||
|
return any.TypeUrl[slash+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any.
|
||||||
|
func MarshalAny(pb proto.Message) (*any.Any, error) {
|
||||||
|
value, err := proto.Marshal(pb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DynamicAny is a value that can be passed to UnmarshalAny to automatically
|
||||||
|
// allocate a proto.Message for the type specified in a google.protobuf.Any
|
||||||
|
// message. The allocated message is stored in the embedded proto.Message.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// var x ptypes.DynamicAny
|
||||||
|
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
|
||||||
|
// fmt.Printf("unmarshaled message: %v", x.Message)
|
||||||
|
type DynamicAny struct {
|
||||||
|
proto.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns a new proto.Message of the type specified in a
|
||||||
|
// google.protobuf.Any message. It returns an error if corresponding message
|
||||||
|
// type isn't linked in.
|
||||||
|
func Empty(any *any.Any) (proto.Message, error) {
|
||||||
|
aname, err := AnyMessageName(any)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t := proto.MessageType(aname)
|
||||||
|
if t == nil {
|
||||||
|
return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
|
||||||
|
}
|
||||||
|
return reflect.New(t.Elem()).Interface().(proto.Message), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any
|
||||||
|
// message and places the decoded result in pb. It returns an error if type of
|
||||||
|
// contents of Any message does not match type of pb message.
|
||||||
|
//
|
||||||
|
// pb can be a proto.Message, or a *DynamicAny.
|
||||||
|
func UnmarshalAny(any *any.Any, pb proto.Message) error {
|
||||||
|
if d, ok := pb.(*DynamicAny); ok {
|
||||||
|
if d.Message == nil {
|
||||||
|
var err error
|
||||||
|
d.Message, err = Empty(any)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UnmarshalAny(any, d.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
aname, err := AnyMessageName(any)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mname := proto.MessageName(pb)
|
||||||
|
if aname != mname {
|
||||||
|
return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
|
||||||
|
}
|
||||||
|
return proto.Unmarshal(any.Value, pb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is returns true if any value contains a given message type.
|
||||||
|
func Is(any *any.Any, pb proto.Message) bool {
|
||||||
|
aname, err := AnyMessageName(any)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return aname == proto.MessageName(pb)
|
||||||
|
}
|
|
@ -1,31 +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.
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// Code generated by protoc-gen-go.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: github.com/golang/protobuf/ptypes/any/any.proto
|
// source: google/protobuf/any.proto
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package any is a generated protocol buffer package.
|
Package any is a generated protocol buffer package.
|
||||||
|
|
||||||
It is generated from these files:
|
It is generated from these files:
|
||||||
github.com/golang/protobuf/ptypes/any/any.proto
|
google/protobuf/any.proto
|
||||||
|
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
Any
|
Any
|
||||||
|
@ -63,6 +62,16 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
// any.Unpack(foo)
|
// any.Unpack(foo)
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
|
// Example 4: Pack and unpack a message in Go
|
||||||
|
//
|
||||||
|
// foo := &pb.Foo{...}
|
||||||
|
// any, err := ptypes.MarshalAny(foo)
|
||||||
|
// ...
|
||||||
|
// foo := &pb.Foo{}
|
||||||
|
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
// The pack methods provided by protobuf library will by default use
|
// The pack methods provided by protobuf library will by default use
|
||||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||||
// methods only use the fully qualified type name after the last '/'
|
// methods only use the fully qualified type name after the last '/'
|
||||||
|
@ -132,24 +141,38 @@ func (*Any) ProtoMessage() {}
|
||||||
func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||||
|
|
||||||
|
func (m *Any) GetTypeUrl() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.TypeUrl
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Any) GetValue() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("github.com/golang/protobuf/ptypes/any/any.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 187 bytes of a gzipped FileDescriptorProto
|
// 185 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xcf, 0x2c, 0xc9,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||||
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28,
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||||
0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcc,
|
0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x25, 0x33, 0x2e, 0x66, 0xc7, 0xbc, 0x4a,
|
||||||
0xab, 0x04, 0x61, 0x3d, 0xb0, 0xb8, 0x10, 0x7f, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x1e, 0x4c,
|
0x21, 0x49, 0x2e, 0x8e, 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46,
|
||||||
0x95, 0x92, 0x19, 0x17, 0xb3, 0x63, 0x5e, 0xa5, 0x90, 0x24, 0x17, 0x07, 0x48, 0x79, 0x7c, 0x69,
|
0x0d, 0xce, 0x20, 0x76, 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7,
|
||||||
0x51, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24,
|
0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc2, 0x71, 0xca, 0xe7, 0x12, 0x4e, 0xce,
|
||||||
0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0xe1,
|
0xcf, 0xd5, 0x43, 0x33, 0xce, 0x89, 0xc3, 0x31, 0xaf, 0x32, 0x00, 0xc4, 0x09, 0x60, 0x8c, 0x52,
|
||||||
0x38, 0x15, 0x71, 0x09, 0x27, 0xe7, 0xe7, 0xea, 0xa1, 0x19, 0xe7, 0xc4, 0xe1, 0x98, 0x57, 0x19,
|
0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc,
|
||||||
0x00, 0xe2, 0x04, 0x30, 0x46, 0xa9, 0x12, 0xe5, 0xb8, 0x05, 0x8c, 0x8c, 0x8b, 0x98, 0x98, 0xdd,
|
0x4b, 0x47, 0xb8, 0xa8, 0x00, 0x64, 0x7a, 0x31, 0xc8, 0x61, 0x8b, 0x98, 0x98, 0xdd, 0x03, 0x9c,
|
||||||
0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x4c, 0x0b, 0x80, 0xaa, 0xd2, 0x0b, 0x4f, 0xcd, 0xc9,
|
0x56, 0x31, 0xc9, 0xb9, 0x43, 0x8c, 0x0a, 0x80, 0x2a, 0xd1, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce,
|
||||||
0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0xa9, 0x4e, 0x62, 0x03, 0x6b, 0x37, 0x06, 0x04, 0x00,
|
0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0x29, 0x4d, 0x62, 0x03, 0xeb, 0x35, 0x06, 0x04, 0x00, 0x00, 0xff,
|
||||||
0x00, 0xff, 0xff, 0xc6, 0x4d, 0x03, 0x23, 0xf6, 0x00, 0x00, 0x00,
|
0xff, 0x13, 0xf8, 0xe8, 0x42, 0xdd, 0x00, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||||
|
option go_package = "github.com/golang/protobuf/ptypes/any";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "AnyProto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
|
||||||
|
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||||
|
// URL that describes the type of the serialized message.
|
||||||
|
//
|
||||||
|
// Protobuf library provides support to pack/unpack Any values in the form
|
||||||
|
// of utility functions or additional generated methods of the Any type.
|
||||||
|
//
|
||||||
|
// Example 1: Pack and unpack a message in C++.
|
||||||
|
//
|
||||||
|
// Foo foo = ...;
|
||||||
|
// Any any;
|
||||||
|
// any.PackFrom(foo);
|
||||||
|
// ...
|
||||||
|
// if (any.UnpackTo(&foo)) {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 2: Pack and unpack a message in Java.
|
||||||
|
//
|
||||||
|
// Foo foo = ...;
|
||||||
|
// Any any = Any.pack(foo);
|
||||||
|
// ...
|
||||||
|
// if (any.is(Foo.class)) {
|
||||||
|
// foo = any.unpack(Foo.class);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 3: Pack and unpack a message in Python.
|
||||||
|
//
|
||||||
|
// foo = Foo(...)
|
||||||
|
// any = Any()
|
||||||
|
// any.Pack(foo)
|
||||||
|
// ...
|
||||||
|
// if any.Is(Foo.DESCRIPTOR):
|
||||||
|
// any.Unpack(foo)
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// Example 4: Pack and unpack a message in Go
|
||||||
|
//
|
||||||
|
// foo := &pb.Foo{...}
|
||||||
|
// any, err := ptypes.MarshalAny(foo)
|
||||||
|
// ...
|
||||||
|
// foo := &pb.Foo{}
|
||||||
|
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The pack methods provided by protobuf library will by default use
|
||||||
|
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||||
|
// methods only use the fully qualified type name after the last '/'
|
||||||
|
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||||
|
// name "y.z".
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// JSON
|
||||||
|
// ====
|
||||||
|
// The JSON representation of an `Any` value uses the regular
|
||||||
|
// representation of the deserialized, embedded message, with an
|
||||||
|
// additional field `@type` which contains the type URL. Example:
|
||||||
|
//
|
||||||
|
// package google.profile;
|
||||||
|
// message Person {
|
||||||
|
// string first_name = 1;
|
||||||
|
// string last_name = 2;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "@type": "type.googleapis.com/google.profile.Person",
|
||||||
|
// "firstName": <string>,
|
||||||
|
// "lastName": <string>
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If the embedded message type is well-known and has a custom JSON
|
||||||
|
// representation, that representation will be embedded adding a field
|
||||||
|
// `value` which holds the custom JSON in addition to the `@type`
|
||||||
|
// field. Example (for message [google.protobuf.Duration][]):
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||||
|
// "value": "1.212s"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
message Any {
|
||||||
|
// A URL/resource name whose content describes the type of the
|
||||||
|
// serialized protocol buffer message.
|
||||||
|
//
|
||||||
|
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||||
|
// following restrictions and interpretations apply:
|
||||||
|
//
|
||||||
|
// * If no scheme is provided, `https` is assumed.
|
||||||
|
// * The last segment of the URL's path must represent the fully
|
||||||
|
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||||
|
// The name should be in a canonical form (e.g., leading "." is
|
||||||
|
// not accepted).
|
||||||
|
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||||
|
// value in binary format, or produce an error.
|
||||||
|
// * Applications are allowed to cache lookup results based on the
|
||||||
|
// URL, or have them precompiled into a binary to avoid any
|
||||||
|
// lookup. Therefore, binary compatibility needs to be preserved
|
||||||
|
// on changes to types. (Use versioned type names to manage
|
||||||
|
// breaking changes.)
|
||||||
|
//
|
||||||
|
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||||
|
// used with implementation specific semantics.
|
||||||
|
//
|
||||||
|
string type_url = 1;
|
||||||
|
|
||||||
|
// Must be a valid serialized protocol buffer of the above specified type.
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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 ptypes contains code for interacting with well-known types.
|
||||||
|
*/
|
||||||
|
package ptypes
|
|
@ -0,0 +1,102 @@
|
||||||
|
// 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 ptypes
|
||||||
|
|
||||||
|
// This file implements conversions between google.protobuf.Duration
|
||||||
|
// and time.Duration.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
durpb "github.com/golang/protobuf/ptypes/duration"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Range of a durpb.Duration in seconds, as specified in
|
||||||
|
// google/protobuf/duration.proto. This is about 10,000 years in seconds.
|
||||||
|
maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
|
||||||
|
minSeconds = -maxSeconds
|
||||||
|
)
|
||||||
|
|
||||||
|
// validateDuration determines whether the durpb.Duration is valid according to the
|
||||||
|
// definition in google/protobuf/duration.proto. A valid durpb.Duration
|
||||||
|
// may still be too large to fit into a time.Duration (the range of durpb.Duration
|
||||||
|
// is about 10,000 years, and the range of time.Duration is about 290).
|
||||||
|
func validateDuration(d *durpb.Duration) error {
|
||||||
|
if d == nil {
|
||||||
|
return errors.New("duration: nil Duration")
|
||||||
|
}
|
||||||
|
if d.Seconds < minSeconds || d.Seconds > maxSeconds {
|
||||||
|
return fmt.Errorf("duration: %v: seconds out of range", d)
|
||||||
|
}
|
||||||
|
if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
|
||||||
|
return fmt.Errorf("duration: %v: nanos out of range", d)
|
||||||
|
}
|
||||||
|
// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
|
||||||
|
if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
|
||||||
|
return fmt.Errorf("duration: %v: seconds and nanos have different signs", d)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration converts a durpb.Duration to a time.Duration. Duration
|
||||||
|
// returns an error if the durpb.Duration is invalid or is too large to be
|
||||||
|
// represented in a time.Duration.
|
||||||
|
func Duration(p *durpb.Duration) (time.Duration, error) {
|
||||||
|
if err := validateDuration(p); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d := time.Duration(p.Seconds) * time.Second
|
||||||
|
if int64(d/time.Second) != p.Seconds {
|
||||||
|
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||||
|
}
|
||||||
|
if p.Nanos != 0 {
|
||||||
|
d += time.Duration(p.Nanos)
|
||||||
|
if (d < 0) != (p.Nanos < 0) {
|
||||||
|
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationProto converts a time.Duration to a durpb.Duration.
|
||||||
|
func DurationProto(d time.Duration) *durpb.Duration {
|
||||||
|
nanos := d.Nanoseconds()
|
||||||
|
secs := nanos / 1e9
|
||||||
|
nanos -= secs * 1e9
|
||||||
|
return &durpb.Duration{
|
||||||
|
Seconds: secs,
|
||||||
|
Nanos: int32(nanos),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: google/protobuf/duration.proto
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package duration is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
google/protobuf/duration.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
Duration
|
||||||
|
*/
|
||||||
|
package duration
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
// A Duration represents a signed, fixed-length span of time represented
|
||||||
|
// as a count of seconds and fractions of seconds at nanosecond
|
||||||
|
// resolution. It is independent of any calendar and concepts like "day"
|
||||||
|
// or "month". It is related to Timestamp in that the difference between
|
||||||
|
// two Timestamp values is a Duration and it can be added or subtracted
|
||||||
|
// from a Timestamp. Range is approximately +-10,000 years.
|
||||||
|
//
|
||||||
|
// # Examples
|
||||||
|
//
|
||||||
|
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
||||||
|
//
|
||||||
|
// Timestamp start = ...;
|
||||||
|
// Timestamp end = ...;
|
||||||
|
// Duration duration = ...;
|
||||||
|
//
|
||||||
|
// duration.seconds = end.seconds - start.seconds;
|
||||||
|
// duration.nanos = end.nanos - start.nanos;
|
||||||
|
//
|
||||||
|
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||||
|
// duration.seconds += 1;
|
||||||
|
// duration.nanos -= 1000000000;
|
||||||
|
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
||||||
|
// duration.seconds -= 1;
|
||||||
|
// duration.nanos += 1000000000;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
||||||
|
//
|
||||||
|
// Timestamp start = ...;
|
||||||
|
// Duration duration = ...;
|
||||||
|
// Timestamp end = ...;
|
||||||
|
//
|
||||||
|
// end.seconds = start.seconds + duration.seconds;
|
||||||
|
// end.nanos = start.nanos + duration.nanos;
|
||||||
|
//
|
||||||
|
// if (end.nanos < 0) {
|
||||||
|
// end.seconds -= 1;
|
||||||
|
// end.nanos += 1000000000;
|
||||||
|
// } else if (end.nanos >= 1000000000) {
|
||||||
|
// end.seconds += 1;
|
||||||
|
// end.nanos -= 1000000000;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 3: Compute Duration from datetime.timedelta in Python.
|
||||||
|
//
|
||||||
|
// td = datetime.timedelta(days=3, minutes=10)
|
||||||
|
// duration = Duration()
|
||||||
|
// duration.FromTimedelta(td)
|
||||||
|
//
|
||||||
|
// # JSON Mapping
|
||||||
|
//
|
||||||
|
// In JSON format, the Duration type is encoded as a string rather than an
|
||||||
|
// object, where the string ends in the suffix "s" (indicating seconds) and
|
||||||
|
// is preceded by the number of seconds, with nanoseconds expressed as
|
||||||
|
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
|
||||||
|
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
|
||||||
|
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
|
||||||
|
// microsecond should be expressed in JSON format as "3.000001s".
|
||||||
|
//
|
||||||
|
//
|
||||||
|
type Duration struct {
|
||||||
|
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||||
|
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||||
|
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||||
|
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||||
|
// Signed fractions of a second at nanosecond resolution of the span
|
||||||
|
// of time. Durations less than one second are represented with a 0
|
||||||
|
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||||
|
// of one second or more, a non-zero value for the `nanos` field must be
|
||||||
|
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||||
|
// to +999,999,999 inclusive.
|
||||||
|
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Duration) Reset() { *m = Duration{} }
|
||||||
|
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*Duration) ProtoMessage() {}
|
||||||
|
func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||||
|
|
||||||
|
func (m *Duration) GetSeconds() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Seconds
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Duration) GetNanos() int32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Nanos
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor0) }
|
||||||
|
|
||||||
|
var fileDescriptor0 = []byte{
|
||||||
|
// 190 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||||
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
||||||
|
0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0x56,
|
||||||
|
0x5c, 0x1c, 0x2e, 0x50, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0xc9, 0xf9, 0x79, 0x29, 0xc5,
|
||||||
|
0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x5e, 0x62, 0x5e,
|
||||||
|
0x7e, 0xb1, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x84, 0xe3, 0x54, 0xc3, 0x25, 0x9c, 0x9c,
|
||||||
|
0x9f, 0xab, 0x87, 0x66, 0xa4, 0x13, 0x2f, 0xcc, 0xc0, 0x00, 0x90, 0x48, 0x00, 0x63, 0x94, 0x56,
|
||||||
|
0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e,
|
||||||
|
0x3a, 0xc2, 0x7d, 0x05, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x70, 0x67, 0xfe, 0x60, 0x64, 0x5c, 0xc4,
|
||||||
|
0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, 0x00, 0x54, 0xa9, 0x5e, 0x78,
|
||||||
|
0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, 0x12, 0x1b, 0xd8, 0x0c, 0x63,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x84, 0x30, 0xff, 0xf3, 0x00, 0x00, 0x00,
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option go_package = "github.com/golang/protobuf/ptypes/duration";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "DurationProto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
|
||||||
|
// A Duration represents a signed, fixed-length span of time represented
|
||||||
|
// as a count of seconds and fractions of seconds at nanosecond
|
||||||
|
// resolution. It is independent of any calendar and concepts like "day"
|
||||||
|
// or "month". It is related to Timestamp in that the difference between
|
||||||
|
// two Timestamp values is a Duration and it can be added or subtracted
|
||||||
|
// from a Timestamp. Range is approximately +-10,000 years.
|
||||||
|
//
|
||||||
|
// # Examples
|
||||||
|
//
|
||||||
|
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
||||||
|
//
|
||||||
|
// Timestamp start = ...;
|
||||||
|
// Timestamp end = ...;
|
||||||
|
// Duration duration = ...;
|
||||||
|
//
|
||||||
|
// duration.seconds = end.seconds - start.seconds;
|
||||||
|
// duration.nanos = end.nanos - start.nanos;
|
||||||
|
//
|
||||||
|
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||||
|
// duration.seconds += 1;
|
||||||
|
// duration.nanos -= 1000000000;
|
||||||
|
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
||||||
|
// duration.seconds -= 1;
|
||||||
|
// duration.nanos += 1000000000;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
||||||
|
//
|
||||||
|
// Timestamp start = ...;
|
||||||
|
// Duration duration = ...;
|
||||||
|
// Timestamp end = ...;
|
||||||
|
//
|
||||||
|
// end.seconds = start.seconds + duration.seconds;
|
||||||
|
// end.nanos = start.nanos + duration.nanos;
|
||||||
|
//
|
||||||
|
// if (end.nanos < 0) {
|
||||||
|
// end.seconds -= 1;
|
||||||
|
// end.nanos += 1000000000;
|
||||||
|
// } else if (end.nanos >= 1000000000) {
|
||||||
|
// end.seconds += 1;
|
||||||
|
// end.nanos -= 1000000000;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example 3: Compute Duration from datetime.timedelta in Python.
|
||||||
|
//
|
||||||
|
// td = datetime.timedelta(days=3, minutes=10)
|
||||||
|
// duration = Duration()
|
||||||
|
// duration.FromTimedelta(td)
|
||||||
|
//
|
||||||
|
// # JSON Mapping
|
||||||
|
//
|
||||||
|
// In JSON format, the Duration type is encoded as a string rather than an
|
||||||
|
// object, where the string ends in the suffix "s" (indicating seconds) and
|
||||||
|
// is preceded by the number of seconds, with nanoseconds expressed as
|
||||||
|
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
|
||||||
|
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
|
||||||
|
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
|
||||||
|
// microsecond should be expressed in JSON format as "3.000001s".
|
||||||
|
//
|
||||||
|
//
|
||||||
|
message Duration {
|
||||||
|
|
||||||
|
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||||
|
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||||
|
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||||
|
int64 seconds = 1;
|
||||||
|
|
||||||
|
// Signed fractions of a second at nanosecond resolution of the span
|
||||||
|
// of time. Durations less than one second are represented with a 0
|
||||||
|
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||||
|
// of one second or more, a non-zero value for the `nanos` field must be
|
||||||
|
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||||
|
// to +999,999,999 inclusive.
|
||||||
|
int32 nanos = 2;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# This script fetches and rebuilds the "well-known types" protocol buffers.
|
||||||
|
# To run this you will need protoc and goprotobuf installed;
|
||||||
|
# see https://github.com/golang/protobuf for instructions.
|
||||||
|
# You also need Go and Git installed.
|
||||||
|
|
||||||
|
PKG=github.com/golang/protobuf/ptypes
|
||||||
|
UPSTREAM=https://github.com/google/protobuf
|
||||||
|
UPSTREAM_SUBDIR=src/google/protobuf
|
||||||
|
PROTO_FILES=(any duration empty struct timestamp wrappers)
|
||||||
|
|
||||||
|
function die() {
|
||||||
|
echo 1>&2 $*
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sanity check that the right tools are accessible.
|
||||||
|
for tool in go git protoc protoc-gen-go; do
|
||||||
|
q=$(which $tool) || die "didn't find $tool"
|
||||||
|
echo 1>&2 "$tool: $q"
|
||||||
|
done
|
||||||
|
|
||||||
|
tmpdir=$(mktemp -d -t regen-wkt.XXXXXX)
|
||||||
|
trap 'rm -rf $tmpdir' EXIT
|
||||||
|
|
||||||
|
echo -n 1>&2 "finding package dir... "
|
||||||
|
pkgdir=$(go list -f '{{.Dir}}' $PKG)
|
||||||
|
echo 1>&2 $pkgdir
|
||||||
|
base=$(echo $pkgdir | sed "s,/$PKG\$,,")
|
||||||
|
echo 1>&2 "base: $base"
|
||||||
|
cd "$base"
|
||||||
|
|
||||||
|
echo 1>&2 "fetching latest protos... "
|
||||||
|
git clone -q $UPSTREAM $tmpdir
|
||||||
|
|
||||||
|
for file in ${PROTO_FILES[@]}; do
|
||||||
|
echo 1>&2 "* $file"
|
||||||
|
protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die
|
||||||
|
cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file
|
||||||
|
done
|
||||||
|
|
||||||
|
echo 1>&2 "All OK"
|
|
@ -0,0 +1,134 @@
|
||||||
|
// 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 ptypes
|
||||||
|
|
||||||
|
// This file implements operations on google.protobuf.Timestamp.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
tspb "github.com/golang/protobuf/ptypes/timestamp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Seconds field of the earliest valid Timestamp.
|
||||||
|
// This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
|
||||||
|
minValidSeconds = -62135596800
|
||||||
|
// Seconds field just after the latest valid Timestamp.
|
||||||
|
// This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
|
||||||
|
maxValidSeconds = 253402300800
|
||||||
|
)
|
||||||
|
|
||||||
|
// validateTimestamp determines whether a Timestamp is valid.
|
||||||
|
// A valid timestamp represents a time in the range
|
||||||
|
// [0001-01-01, 10000-01-01) and has a Nanos field
|
||||||
|
// in the range [0, 1e9).
|
||||||
|
//
|
||||||
|
// If the Timestamp is valid, validateTimestamp returns nil.
|
||||||
|
// Otherwise, it returns an error that describes
|
||||||
|
// the problem.
|
||||||
|
//
|
||||||
|
// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
|
||||||
|
func validateTimestamp(ts *tspb.Timestamp) error {
|
||||||
|
if ts == nil {
|
||||||
|
return errors.New("timestamp: nil Timestamp")
|
||||||
|
}
|
||||||
|
if ts.Seconds < minValidSeconds {
|
||||||
|
return fmt.Errorf("timestamp: %v before 0001-01-01", ts)
|
||||||
|
}
|
||||||
|
if ts.Seconds >= maxValidSeconds {
|
||||||
|
return fmt.Errorf("timestamp: %v after 10000-01-01", ts)
|
||||||
|
}
|
||||||
|
if ts.Nanos < 0 || ts.Nanos >= 1e9 {
|
||||||
|
return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp converts a google.protobuf.Timestamp proto to a time.Time.
|
||||||
|
// It returns an error if the argument is invalid.
|
||||||
|
//
|
||||||
|
// Unlike most Go functions, if Timestamp returns an error, the first return value
|
||||||
|
// is not the zero time.Time. Instead, it is the value obtained from the
|
||||||
|
// time.Unix function when passed the contents of the Timestamp, in the UTC
|
||||||
|
// locale. This may or may not be a meaningful time; many invalid Timestamps
|
||||||
|
// do map to valid time.Times.
|
||||||
|
//
|
||||||
|
// A nil Timestamp returns an error. The first return value in that case is
|
||||||
|
// undefined.
|
||||||
|
func Timestamp(ts *tspb.Timestamp) (time.Time, error) {
|
||||||
|
// Don't return the zero value on error, because corresponds to a valid
|
||||||
|
// timestamp. Instead return whatever time.Unix gives us.
|
||||||
|
var t time.Time
|
||||||
|
if ts == nil {
|
||||||
|
t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
|
||||||
|
} else {
|
||||||
|
t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
|
||||||
|
}
|
||||||
|
return t, validateTimestamp(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampNow returns a google.protobuf.Timestamp for the current time.
|
||||||
|
func TimestampNow() *tspb.Timestamp {
|
||||||
|
ts, err := TimestampProto(time.Now())
|
||||||
|
if err != nil {
|
||||||
|
panic("ptypes: time.Now() out of Timestamp range")
|
||||||
|
}
|
||||||
|
return ts
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
|
||||||
|
// It returns an error if the resulting Timestamp is invalid.
|
||||||
|
func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
|
||||||
|
seconds := t.Unix()
|
||||||
|
nanos := int32(t.Sub(time.Unix(seconds, 0)))
|
||||||
|
ts := &tspb.Timestamp{
|
||||||
|
Seconds: seconds,
|
||||||
|
Nanos: nanos,
|
||||||
|
}
|
||||||
|
if err := validateTimestamp(ts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid
|
||||||
|
// Timestamps, it returns an error message in parentheses.
|
||||||
|
func TimestampString(ts *tspb.Timestamp) string {
|
||||||
|
t, err := Timestamp(ts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("(%v)", err)
|
||||||
|
}
|
||||||
|
return t.Format(time.RFC3339Nano)
|
||||||
|
}
|
160
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
Normal file
160
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: google/protobuf/timestamp.proto
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package timestamp is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
google/protobuf/timestamp.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
Timestamp
|
||||||
|
*/
|
||||||
|
package timestamp
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
// A Timestamp represents a point in time independent of any time zone
|
||||||
|
// or calendar, represented as seconds and fractions of seconds at
|
||||||
|
// nanosecond resolution in UTC Epoch time. It is encoded using the
|
||||||
|
// Proleptic Gregorian Calendar which extends the Gregorian calendar
|
||||||
|
// backwards to year one. It is encoded assuming all minutes are 60
|
||||||
|
// seconds long, i.e. leap seconds are "smeared" so that no leap second
|
||||||
|
// table is needed for interpretation. Range is from
|
||||||
|
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
|
||||||
|
// By restricting to that range, we ensure that we can convert to
|
||||||
|
// and from RFC 3339 date strings.
|
||||||
|
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
|
||||||
|
//
|
||||||
|
// # Examples
|
||||||
|
//
|
||||||
|
// Example 1: Compute Timestamp from POSIX `time()`.
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(time(NULL));
|
||||||
|
// timestamp.set_nanos(0);
|
||||||
|
//
|
||||||
|
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||||
|
//
|
||||||
|
// struct timeval tv;
|
||||||
|
// gettimeofday(&tv, NULL);
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(tv.tv_sec);
|
||||||
|
// timestamp.set_nanos(tv.tv_usec * 1000);
|
||||||
|
//
|
||||||
|
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||||
|
//
|
||||||
|
// FILETIME ft;
|
||||||
|
// GetSystemTimeAsFileTime(&ft);
|
||||||
|
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||||
|
//
|
||||||
|
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||||
|
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||||
|
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||||
|
//
|
||||||
|
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||||
|
//
|
||||||
|
// long millis = System.currentTimeMillis();
|
||||||
|
//
|
||||||
|
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||||
|
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Example 5: Compute Timestamp from current time in Python.
|
||||||
|
//
|
||||||
|
// timestamp = Timestamp()
|
||||||
|
// timestamp.GetCurrentTime()
|
||||||
|
//
|
||||||
|
// # JSON Mapping
|
||||||
|
//
|
||||||
|
// In JSON format, the Timestamp type is encoded as a string in the
|
||||||
|
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
||||||
|
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
||||||
|
// where {year} is always expressed using four digits while {month}, {day},
|
||||||
|
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||||
|
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||||
|
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||||
|
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||||
|
//
|
||||||
|
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||||
|
// 01:30 UTC on January 15, 2017.
|
||||||
|
//
|
||||||
|
// In JavaScript, one can convert a Date object to this format using the
|
||||||
|
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
|
||||||
|
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||||
|
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||||
|
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||||
|
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
|
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
|
||||||
|
// to obtain a formatter capable of generating timestamps in this format.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
type Timestamp struct {
|
||||||
|
// Represents seconds of UTC time since Unix epoch
|
||||||
|
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
||||||
|
// 9999-12-31T23:59:59Z inclusive.
|
||||||
|
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||||
|
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||||
|
// second values with fractions must still have non-negative nanos values
|
||||||
|
// that count forward in time. Must be from 0 to 999,999,999
|
||||||
|
// inclusive.
|
||||||
|
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||||
|
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*Timestamp) ProtoMessage() {}
|
||||||
|
func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||||
|
|
||||||
|
func (m *Timestamp) GetSeconds() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Seconds
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Timestamp) GetNanos() int32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Nanos
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor0) }
|
||||||
|
|
||||||
|
var fileDescriptor0 = []byte{
|
||||||
|
// 191 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||||
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
||||||
|
0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x03, 0x0b, 0x09, 0xf1, 0x43, 0x14, 0xe8, 0xc1, 0x14, 0x28,
|
||||||
|
0x59, 0x73, 0x71, 0x86, 0xc0, 0xd4, 0x08, 0x49, 0x70, 0xb1, 0x17, 0xa7, 0x26, 0xe7, 0xe7, 0xa5,
|
||||||
|
0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0xc1, 0xb8, 0x42, 0x22, 0x5c, 0xac, 0x79, 0x89,
|
||||||
|
0x79, 0xf9, 0xc5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x10, 0x8e, 0x53, 0x1d, 0x97, 0x70,
|
||||||
|
0x72, 0x7e, 0xae, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, 0x40, 0x42, 0x01, 0x8c, 0x51,
|
||||||
|
0xda, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0x39, 0x89,
|
||||||
|
0x79, 0xe9, 0x08, 0x27, 0x16, 0x94, 0x54, 0x16, 0xa4, 0x16, 0x23, 0x5c, 0xfa, 0x83, 0x91, 0x71,
|
||||||
|
0x11, 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xc9, 0x01, 0x50, 0xb5, 0x7a,
|
||||||
|
0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x3d, 0x49, 0x6c, 0x60, 0x43,
|
||||||
|
0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x77, 0x4a, 0x07, 0xf7, 0x00, 0x00, 0x00,
|
||||||
|
}
|
133
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
Normal file
133
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option go_package = "github.com/golang/protobuf/ptypes/timestamp";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "TimestampProto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
|
||||||
|
// A Timestamp represents a point in time independent of any time zone
|
||||||
|
// or calendar, represented as seconds and fractions of seconds at
|
||||||
|
// nanosecond resolution in UTC Epoch time. It is encoded using the
|
||||||
|
// Proleptic Gregorian Calendar which extends the Gregorian calendar
|
||||||
|
// backwards to year one. It is encoded assuming all minutes are 60
|
||||||
|
// seconds long, i.e. leap seconds are "smeared" so that no leap second
|
||||||
|
// table is needed for interpretation. Range is from
|
||||||
|
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
|
||||||
|
// By restricting to that range, we ensure that we can convert to
|
||||||
|
// and from RFC 3339 date strings.
|
||||||
|
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
|
||||||
|
//
|
||||||
|
// # Examples
|
||||||
|
//
|
||||||
|
// Example 1: Compute Timestamp from POSIX `time()`.
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(time(NULL));
|
||||||
|
// timestamp.set_nanos(0);
|
||||||
|
//
|
||||||
|
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||||
|
//
|
||||||
|
// struct timeval tv;
|
||||||
|
// gettimeofday(&tv, NULL);
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(tv.tv_sec);
|
||||||
|
// timestamp.set_nanos(tv.tv_usec * 1000);
|
||||||
|
//
|
||||||
|
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||||
|
//
|
||||||
|
// FILETIME ft;
|
||||||
|
// GetSystemTimeAsFileTime(&ft);
|
||||||
|
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||||
|
//
|
||||||
|
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||||
|
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||||
|
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||||
|
//
|
||||||
|
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||||
|
//
|
||||||
|
// long millis = System.currentTimeMillis();
|
||||||
|
//
|
||||||
|
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||||
|
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Example 5: Compute Timestamp from current time in Python.
|
||||||
|
//
|
||||||
|
// timestamp = Timestamp()
|
||||||
|
// timestamp.GetCurrentTime()
|
||||||
|
//
|
||||||
|
// # JSON Mapping
|
||||||
|
//
|
||||||
|
// In JSON format, the Timestamp type is encoded as a string in the
|
||||||
|
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
||||||
|
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
||||||
|
// where {year} is always expressed using four digits while {month}, {day},
|
||||||
|
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||||
|
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||||
|
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||||
|
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||||
|
//
|
||||||
|
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||||
|
// 01:30 UTC on January 15, 2017.
|
||||||
|
//
|
||||||
|
// In JavaScript, one can convert a Date object to this format using the
|
||||||
|
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
|
||||||
|
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||||
|
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||||
|
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||||
|
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
|
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
|
||||||
|
// to obtain a formatter capable of generating timestamps in this format.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
message Timestamp {
|
||||||
|
|
||||||
|
// Represents seconds of UTC time since Unix epoch
|
||||||
|
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
||||||
|
// 9999-12-31T23:59:59Z inclusive.
|
||||||
|
int64 seconds = 1;
|
||||||
|
|
||||||
|
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||||
|
// second values with fractions must still have non-negative nanos values
|
||||||
|
// that count forward in time. Must be from 0 to 999,999,999
|
||||||
|
// inclusive.
|
||||||
|
int32 nanos = 2;
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ import (
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CallOption is an option used by Invoke to control behaviors of RPC calls.
|
// CallOption is an option used by Invoke to control behaviors of RPC calls.
|
||||||
|
@ -80,7 +81,11 @@ type boRetryer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *boRetryer) Retry(err error) (time.Duration, bool) {
|
func (r *boRetryer) Retry(err error) (time.Duration, bool) {
|
||||||
c := grpc.Code(err)
|
st, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
c := st.Code()
|
||||||
for _, rc := range r.codes {
|
for _, rc := range r.codes {
|
||||||
if c == rc {
|
if c == rc {
|
||||||
return r.backoff.Pause(), true
|
return r.backoff.Pause(), true
|
||||||
|
@ -121,6 +126,9 @@ func (bo *Backoff) Pause() time.Duration {
|
||||||
if bo.Multiplier < 1 {
|
if bo.Multiplier < 1 {
|
||||||
bo.Multiplier = 2
|
bo.Multiplier = 2
|
||||||
}
|
}
|
||||||
|
// Select a duration between zero and the current max. It might seem counterintuitive to
|
||||||
|
// have so much jitter, but https://www.awsarchitectureblog.com/2015/03/backoff.html
|
||||||
|
// argues that that is the best strategy.
|
||||||
d := time.Duration(rand.Int63n(int64(bo.cur)))
|
d := time.Duration(rand.Int63n(int64(bo.cur)))
|
||||||
bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier)
|
bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier)
|
||||||
if bo.cur > bo.Max {
|
if bo.cur > bo.Max {
|
||||||
|
@ -129,8 +137,21 @@ func (bo *Backoff) Pause() time.Duration {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type grpcOpt []grpc.CallOption
|
||||||
|
|
||||||
|
func (o grpcOpt) Resolve(s *CallSettings) {
|
||||||
|
s.GRPC = o
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithGRPCOptions(opt ...grpc.CallOption) CallOption {
|
||||||
|
return grpcOpt(append([]grpc.CallOption(nil), opt...))
|
||||||
|
}
|
||||||
|
|
||||||
type CallSettings struct {
|
type CallSettings struct {
|
||||||
// Retry returns a Retryer to be used to control retry logic of a method call.
|
// Retry returns a Retryer to be used to control retry logic of a method call.
|
||||||
// If Retry is nil or the returned Retryer is nil, the call will not be retried.
|
// If Retry is nil or the returned Retryer is nil, the call will not be retried.
|
||||||
Retry func() Retryer
|
Retry func() Retryer
|
||||||
|
|
||||||
|
// CallOptions to be forwarded to GRPC.
|
||||||
|
GRPC []grpc.CallOption
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package gax
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
// XGoogHeader is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// XGoogHeader formats key-value pairs.
|
||||||
|
// The resulting string is suitable for x-goog-api-client header.
|
||||||
|
func XGoogHeader(keyval ...string) string {
|
||||||
|
if len(keyval) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(keyval)%2 != 0 {
|
||||||
|
panic("gax.Header: odd argument count")
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i := 0; i < len(keyval); i += 2 {
|
||||||
|
buf.WriteByte(' ')
|
||||||
|
buf.WriteString(keyval[i])
|
||||||
|
buf.WriteByte('/')
|
||||||
|
buf.WriteString(keyval[i+1])
|
||||||
|
}
|
||||||
|
return buf.String()[1:]
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// A user defined call stub.
|
// A user defined call stub.
|
||||||
type APICall func(context.Context) error
|
type APICall func(context.Context, CallSettings) error
|
||||||
|
|
||||||
// Invoke calls the given APICall,
|
// Invoke calls the given APICall,
|
||||||
// performing retries as specified by opts, if any.
|
// performing retries as specified by opts, if any.
|
||||||
|
@ -67,7 +67,7 @@ type sleeper func(ctx context.Context, d time.Duration) error
|
||||||
func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper) error {
|
func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper) error {
|
||||||
var retryer Retryer
|
var retryer Retryer
|
||||||
for {
|
for {
|
||||||
err := call(ctx)
|
err := call(ctx, settings)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
// Copyright 2016, Google Inc.
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
package gax
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type matcher interface {
|
|
||||||
match([]string) (int, error)
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
type segment struct {
|
|
||||||
matcher
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
type labelMatcher string
|
|
||||||
|
|
||||||
func (ls labelMatcher) match(segments []string) (int, error) {
|
|
||||||
if len(segments) == 0 {
|
|
||||||
return 0, fmt.Errorf("expected %s but no more segments found", ls)
|
|
||||||
}
|
|
||||||
if segments[0] != string(ls) {
|
|
||||||
return 0, fmt.Errorf("expected %s but got %s", ls, segments[0])
|
|
||||||
}
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ls labelMatcher) String() string {
|
|
||||||
return string(ls)
|
|
||||||
}
|
|
||||||
|
|
||||||
type wildcardMatcher int
|
|
||||||
|
|
||||||
func (wm wildcardMatcher) match(segments []string) (int, error) {
|
|
||||||
if len(segments) == 0 {
|
|
||||||
return 0, errors.New("no more segments found")
|
|
||||||
}
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm wildcardMatcher) String() string {
|
|
||||||
return "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
type pathWildcardMatcher int
|
|
||||||
|
|
||||||
func (pwm pathWildcardMatcher) match(segments []string) (int, error) {
|
|
||||||
length := len(segments) - int(pwm)
|
|
||||||
if length <= 0 {
|
|
||||||
return 0, errors.New("not sufficient segments are supplied for path wildcard")
|
|
||||||
}
|
|
||||||
return length, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pwm pathWildcardMatcher) String() string {
|
|
||||||
return "**"
|
|
||||||
}
|
|
||||||
|
|
||||||
type ParseError struct {
|
|
||||||
Pos int
|
|
||||||
Template string
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pe ParseError) Error() string {
|
|
||||||
return fmt.Sprintf("at %d of template '%s', %s", pe.Pos, pe.Template, pe.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PathTemplate manages the template to build and match with paths used
|
|
||||||
// by API services. It holds a template and variable names in it, and
|
|
||||||
// it can extract matched patterns from a path string or build a path
|
|
||||||
// string from a binding.
|
|
||||||
//
|
|
||||||
// See http.proto in github.com/googleapis/googleapis/ for the details of
|
|
||||||
// the template syntax.
|
|
||||||
type PathTemplate struct {
|
|
||||||
segments []segment
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPathTemplate parses a path template, and returns a PathTemplate
|
|
||||||
// instance if successful.
|
|
||||||
func NewPathTemplate(template string) (*PathTemplate, error) {
|
|
||||||
return parsePathTemplate(template)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustCompilePathTemplate is like NewPathTemplate but panics if the
|
|
||||||
// expression cannot be parsed. It simplifies safe initialization of
|
|
||||||
// global variables holding compiled regular expressions.
|
|
||||||
func MustCompilePathTemplate(template string) *PathTemplate {
|
|
||||||
pt, err := NewPathTemplate(template)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return pt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match attempts to match the given path with the template, and returns
|
|
||||||
// the mapping of the variable name to the matched pattern string.
|
|
||||||
func (pt *PathTemplate) Match(path string) (map[string]string, error) {
|
|
||||||
paths := strings.Split(path, "/")
|
|
||||||
values := map[string]string{}
|
|
||||||
for _, segment := range pt.segments {
|
|
||||||
length, err := segment.match(paths)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if segment.name != "" {
|
|
||||||
value := strings.Join(paths[:length], "/")
|
|
||||||
if oldValue, ok := values[segment.name]; ok {
|
|
||||||
values[segment.name] = oldValue + "/" + value
|
|
||||||
} else {
|
|
||||||
values[segment.name] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paths = paths[length:]
|
|
||||||
}
|
|
||||||
if len(paths) != 0 {
|
|
||||||
return nil, fmt.Errorf("Trailing path %s remains after the matching", strings.Join(paths, "/"))
|
|
||||||
}
|
|
||||||
return values, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render creates a path string from its template and the binding from
|
|
||||||
// the variable name to the value.
|
|
||||||
func (pt *PathTemplate) Render(binding map[string]string) (string, error) {
|
|
||||||
result := make([]string, 0, len(pt.segments))
|
|
||||||
var lastVariableName string
|
|
||||||
for _, segment := range pt.segments {
|
|
||||||
name := segment.name
|
|
||||||
if lastVariableName != "" && name == lastVariableName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lastVariableName = name
|
|
||||||
if name == "" {
|
|
||||||
result = append(result, segment.String())
|
|
||||||
} else if value, ok := binding[name]; ok {
|
|
||||||
result = append(result, value)
|
|
||||||
} else {
|
|
||||||
return "", fmt.Errorf("%s is not found", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
built := strings.Join(result, "/")
|
|
||||||
return built, nil
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
// Copyright 2016, Google Inc.
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
package gax
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This parser follows the syntax of path templates, from
|
|
||||||
// https://github.com/googleapis/googleapis/blob/master/google/api/http.proto.
|
|
||||||
// The differences are that there is no custom verb, we allow the initial slash
|
|
||||||
// to be absent, and that we are not strict as
|
|
||||||
// https://tools.ietf.org/html/rfc6570 about the characters in identifiers and
|
|
||||||
// literals.
|
|
||||||
|
|
||||||
type pathTemplateParser struct {
|
|
||||||
r *strings.Reader
|
|
||||||
runeCount int // the number of the current rune in the original string
|
|
||||||
nextVar int // the number to use for the next unnamed variable
|
|
||||||
seenName map[string]bool // names we've seen already
|
|
||||||
seenPathWildcard bool // have we seen "**" already?
|
|
||||||
}
|
|
||||||
|
|
||||||
func parsePathTemplate(template string) (pt *PathTemplate, err error) {
|
|
||||||
p := &pathTemplateParser{
|
|
||||||
r: strings.NewReader(template),
|
|
||||||
seenName: map[string]bool{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle panics with strings like errors.
|
|
||||||
// See pathTemplateParser.error, below.
|
|
||||||
defer func() {
|
|
||||||
if x := recover(); x != nil {
|
|
||||||
errmsg, ok := x.(errString)
|
|
||||||
if !ok {
|
|
||||||
panic(x)
|
|
||||||
}
|
|
||||||
pt = nil
|
|
||||||
err = ParseError{p.runeCount, template, string(errmsg)}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
segs := p.template()
|
|
||||||
// If there is a path wildcard, set its length. We can't do this
|
|
||||||
// until we know how many segments we've got all together.
|
|
||||||
for i, seg := range segs {
|
|
||||||
if _, ok := seg.matcher.(pathWildcardMatcher); ok {
|
|
||||||
segs[i].matcher = pathWildcardMatcher(len(segs) - i - 1)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &PathTemplate{segments: segs}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to indicate errors "thrown" by this parser. We don't use string because
|
|
||||||
// many parts of the standard library panic with strings.
|
|
||||||
type errString string
|
|
||||||
|
|
||||||
// Terminates parsing immediately with an error.
|
|
||||||
func (p *pathTemplateParser) error(msg string) {
|
|
||||||
panic(errString(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template = [ "/" ] Segments
|
|
||||||
func (p *pathTemplateParser) template() []segment {
|
|
||||||
var segs []segment
|
|
||||||
if p.consume('/') {
|
|
||||||
// Initial '/' needs an initial empty matcher.
|
|
||||||
segs = append(segs, segment{matcher: labelMatcher("")})
|
|
||||||
}
|
|
||||||
return append(segs, p.segments("")...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Segments = Segment { "/" Segment }
|
|
||||||
func (p *pathTemplateParser) segments(name string) []segment {
|
|
||||||
var segs []segment
|
|
||||||
for {
|
|
||||||
subsegs := p.segment(name)
|
|
||||||
segs = append(segs, subsegs...)
|
|
||||||
if !p.consume('/') {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return segs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Segment = "*" | "**" | LITERAL | Variable
|
|
||||||
func (p *pathTemplateParser) segment(name string) []segment {
|
|
||||||
if p.consume('*') {
|
|
||||||
if name == "" {
|
|
||||||
name = fmt.Sprintf("$%d", p.nextVar)
|
|
||||||
p.nextVar++
|
|
||||||
}
|
|
||||||
if p.consume('*') {
|
|
||||||
if p.seenPathWildcard {
|
|
||||||
p.error("multiple '**' disallowed")
|
|
||||||
}
|
|
||||||
p.seenPathWildcard = true
|
|
||||||
// We'll change 0 to the right number at the end.
|
|
||||||
return []segment{{name: name, matcher: pathWildcardMatcher(0)}}
|
|
||||||
}
|
|
||||||
return []segment{{name: name, matcher: wildcardMatcher(0)}}
|
|
||||||
}
|
|
||||||
if p.consume('{') {
|
|
||||||
if name != "" {
|
|
||||||
p.error("recursive named bindings are not allowed")
|
|
||||||
}
|
|
||||||
return p.variable()
|
|
||||||
}
|
|
||||||
return []segment{{name: name, matcher: labelMatcher(p.literal())}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable = "{" FieldPath [ "=" Segments ] "}"
|
|
||||||
// "{" is already consumed.
|
|
||||||
func (p *pathTemplateParser) variable() []segment {
|
|
||||||
// Simplification: treat FieldPath as LITERAL, instead of IDENT { '.' IDENT }
|
|
||||||
name := p.literal()
|
|
||||||
if p.seenName[name] {
|
|
||||||
p.error(name + " appears multiple times")
|
|
||||||
}
|
|
||||||
p.seenName[name] = true
|
|
||||||
var segs []segment
|
|
||||||
if p.consume('=') {
|
|
||||||
segs = p.segments(name)
|
|
||||||
} else {
|
|
||||||
// "{var}" is equivalent to "{var=*}"
|
|
||||||
segs = []segment{{name: name, matcher: wildcardMatcher(0)}}
|
|
||||||
}
|
|
||||||
if !p.consume('}') {
|
|
||||||
p.error("expected '}'")
|
|
||||||
}
|
|
||||||
return segs
|
|
||||||
}
|
|
||||||
|
|
||||||
// A literal is any sequence of characters other than a few special ones.
|
|
||||||
// The list of stop characters is not quite the same as in the template RFC.
|
|
||||||
func (p *pathTemplateParser) literal() string {
|
|
||||||
lit := p.consumeUntil("/*}{=")
|
|
||||||
if lit == "" {
|
|
||||||
p.error("empty literal")
|
|
||||||
}
|
|
||||||
return lit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read runes until EOF or one of the runes in stopRunes is encountered.
|
|
||||||
// If the latter, unread the stop rune. Return the accumulated runes as a string.
|
|
||||||
func (p *pathTemplateParser) consumeUntil(stopRunes string) string {
|
|
||||||
var runes []rune
|
|
||||||
for {
|
|
||||||
r, ok := p.readRune()
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if strings.IndexRune(stopRunes, r) >= 0 {
|
|
||||||
p.unreadRune()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
runes = append(runes, r)
|
|
||||||
}
|
|
||||||
return string(runes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the next rune is r, consume it and return true.
|
|
||||||
// Otherwise, leave the input unchanged and return false.
|
|
||||||
func (p *pathTemplateParser) consume(r rune) bool {
|
|
||||||
rr, ok := p.readRune()
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if r == rr {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
p.unreadRune()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the next rune from the input. Return it.
|
|
||||||
// The second return value is false at EOF.
|
|
||||||
func (p *pathTemplateParser) readRune() (rune, bool) {
|
|
||||||
r, _, err := p.r.ReadRune()
|
|
||||||
if err == io.EOF {
|
|
||||||
return r, false
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
p.error(err.Error())
|
|
||||||
}
|
|
||||||
p.runeCount++
|
|
||||||
return r, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put the last rune that was read back on the input.
|
|
||||||
func (p *pathTemplateParser) unreadRune() {
|
|
||||||
if err := p.r.UnreadRune(); err != nil {
|
|
||||||
p.error(err.Error())
|
|
||||||
}
|
|
||||||
p.runeCount--
|
|
||||||
}
|
|
|
@ -35,7 +35,7 @@ client.Backoff = func(retry int) time.Duration {
|
||||||
For a complete and working example, see the sample directory.
|
For a complete and working example, see the sample directory.
|
||||||
`pester` allows you to use a constructor to control:
|
`pester` allows you to use a constructor to control:
|
||||||
- backoff strategy
|
- backoff strategy
|
||||||
- reties
|
- retries
|
||||||
- concurrency
|
- concurrency
|
||||||
- keeping a log for debugging
|
- keeping a log for debugging
|
||||||
```go
|
```go
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package pester
|
// Package pester provides additional resiliency over the standard http client methods by
|
||||||
|
|
||||||
// pester provides additional resiliency over the standard http client methods by
|
|
||||||
// allowing you to control concurrency, retries, and a backoff strategy.
|
// allowing you to control concurrency, retries, and a backoff strategy.
|
||||||
|
package pester
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -9,7 +8,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -17,6 +15,15 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//ErrUnexpectedMethod occurs when an http.Client method is unable to be mapped from a calling method in the pester client
|
||||||
|
var ErrUnexpectedMethod = errors.New("unexpected client method, must be one of Do, Get, Head, Post, or PostFrom")
|
||||||
|
|
||||||
|
// ErrReadingBody happens when we cannot read the body bytes
|
||||||
|
var ErrReadingBody = errors.New("error reading body")
|
||||||
|
|
||||||
|
// ErrReadingRequestBody happens when we cannot read the request body bytes
|
||||||
|
var ErrReadingRequestBody = errors.New("error reading request body")
|
||||||
|
|
||||||
// Client wraps the http client and exposes all the functionality of the http.Client.
|
// Client wraps the http client and exposes all the functionality of the http.Client.
|
||||||
// Additionally, Client provides pester specific values for handling resiliency.
|
// Additionally, Client provides pester specific values for handling resiliency.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -33,6 +40,7 @@ type Client struct {
|
||||||
MaxRetries int
|
MaxRetries int
|
||||||
Backoff BackoffStrategy
|
Backoff BackoffStrategy
|
||||||
KeepLog bool
|
KeepLog bool
|
||||||
|
LogHook LogHook
|
||||||
|
|
||||||
SuccessReqNum int
|
SuccessReqNum int
|
||||||
SuccessRetryNum int
|
SuccessRetryNum int
|
||||||
|
@ -76,6 +84,12 @@ type params struct {
|
||||||
data url.Values
|
data url.Values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var random *rand.Rand
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
}
|
||||||
|
|
||||||
// New constructs a new DefaultClient with sensible default values
|
// New constructs a new DefaultClient with sensible default values
|
||||||
func New() *Client {
|
func New() *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
|
@ -95,6 +109,10 @@ func NewExtendedClient(hc *http.Client) *Client {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogHook is used to log attempts as they happen. This function is never called,
|
||||||
|
// however, if KeepLog is set to true.
|
||||||
|
type LogHook func(e ErrEntry)
|
||||||
|
|
||||||
// BackoffStrategy is used to determine how long a retry request should wait until attempted
|
// BackoffStrategy is used to determine how long a retry request should wait until attempted
|
||||||
type BackoffStrategy func(retry int) time.Duration
|
type BackoffStrategy func(retry int) time.Duration
|
||||||
|
|
||||||
|
@ -108,13 +126,13 @@ func DefaultBackoff(_ int) time.Duration {
|
||||||
|
|
||||||
// ExponentialBackoff returns ever increasing backoffs by a power of 2
|
// ExponentialBackoff returns ever increasing backoffs by a power of 2
|
||||||
func ExponentialBackoff(i int) time.Duration {
|
func ExponentialBackoff(i int) time.Duration {
|
||||||
return time.Duration(math.Pow(2, float64(i))) * time.Second
|
return time.Duration(1<<uint(i)) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExponentialJitterBackoff returns ever increasing backoffs by a power of 2
|
// ExponentialJitterBackoff returns ever increasing backoffs by a power of 2
|
||||||
// with +/- 0-33% to prevent sychronized reuqests.
|
// with +/- 0-33% to prevent sychronized reuqests.
|
||||||
func ExponentialJitterBackoff(i int) time.Duration {
|
func ExponentialJitterBackoff(i int) time.Duration {
|
||||||
return jitter(int(math.Pow(2, float64(i))))
|
return jitter(int(1 << uint(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinearBackoff returns increasing durations, each a second longer than the last
|
// LinearBackoff returns increasing durations, each a second longer than the last
|
||||||
|
@ -134,14 +152,8 @@ func jitter(i int) time.Duration {
|
||||||
|
|
||||||
maxJitter := ms / 3
|
maxJitter := ms / 3
|
||||||
|
|
||||||
rand.Seed(time.Now().Unix())
|
// ms ± rand
|
||||||
jitter := rand.Intn(maxJitter + 1)
|
ms += random.Intn(2*maxJitter) - maxJitter
|
||||||
|
|
||||||
if rand.Intn(2) == 1 {
|
|
||||||
ms = ms + jitter
|
|
||||||
} else {
|
|
||||||
ms = ms - jitter
|
|
||||||
}
|
|
||||||
|
|
||||||
// a jitter of 0 messes up the time.Tick chan
|
// a jitter of 0 messes up the time.Tick chan
|
||||||
if ms <= 0 {
|
if ms <= 0 {
|
||||||
|
@ -206,14 +218,14 @@ func (c *Client) pester(p params) (*http.Response, error) {
|
||||||
if p.req != nil && p.req.Body != nil {
|
if p.req != nil && p.req.Body != nil {
|
||||||
originalRequestBody, err = ioutil.ReadAll(p.req.Body)
|
originalRequestBody, err = ioutil.ReadAll(p.req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &http.Response{}, errors.New("error reading request body")
|
return nil, ErrReadingRequestBody
|
||||||
}
|
}
|
||||||
p.req.Body.Close()
|
p.req.Body.Close()
|
||||||
}
|
}
|
||||||
if p.body != nil {
|
if p.body != nil {
|
||||||
originalBody, err = ioutil.ReadAll(p.body)
|
originalBody, err = ioutil.ReadAll(p.body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &http.Response{}, errors.New("error reading body")
|
return nil, ErrReadingBody
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +250,6 @@ func (c *Client) pester(p params) (*http.Response, error) {
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
resp := &http.Response{}
|
|
||||||
|
|
||||||
// rehydrate the body (it is drained each read)
|
// rehydrate the body (it is drained each read)
|
||||||
if len(originalRequestBody) > 0 {
|
if len(originalRequestBody) > 0 {
|
||||||
|
@ -248,6 +259,7 @@ func (c *Client) pester(p params) (*http.Response, error) {
|
||||||
p.body = bytes.NewBuffer(originalBody)
|
p.body = bytes.NewBuffer(originalBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
// route the calls
|
// route the calls
|
||||||
switch p.method {
|
switch p.method {
|
||||||
case "Do":
|
case "Do":
|
||||||
|
@ -260,6 +272,8 @@ func (c *Client) pester(p params) (*http.Response, error) {
|
||||||
resp, err = httpClient.Post(p.url, p.bodyType, p.body)
|
resp, err = httpClient.Post(p.url, p.bodyType, p.body)
|
||||||
case "PostForm":
|
case "PostForm":
|
||||||
resp, err = httpClient.PostForm(p.url, p.data)
|
resp, err = httpClient.PostForm(p.url, p.data)
|
||||||
|
default:
|
||||||
|
err = ErrUnexpectedMethod
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early return if we have a valid result
|
// Early return if we have a valid result
|
||||||
|
@ -320,14 +334,13 @@ func (c *Client) pester(p params) (*http.Response, error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
res := <-resultCh
|
||||||
case res := <-resultCh:
|
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
c.SuccessReqNum = res.req
|
c.SuccessReqNum = res.req
|
||||||
c.SuccessRetryNum = res.retry
|
c.SuccessRetryNum = res.retry
|
||||||
return res.resp, res.err
|
return res.resp, res.err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogString provides a string representation of the errors the client has seen
|
// LogString provides a string representation of the errors the client has seen
|
||||||
|
@ -336,12 +349,17 @@ func (c *Client) LogString() string {
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
var res string
|
var res string
|
||||||
for _, e := range c.ErrLog {
|
for _, e := range c.ErrLog {
|
||||||
res += fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n",
|
res += c.FormatError(e)
|
||||||
e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err)
|
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format the Error to human readable string
|
||||||
|
func (c *Client) FormatError(e ErrEntry) string {
|
||||||
|
return fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n",
|
||||||
|
e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
// LogErrCount is a helper method used primarily for test validation
|
// LogErrCount is a helper method used primarily for test validation
|
||||||
func (c *Client) LogErrCount() int {
|
func (c *Client) LogErrCount() int {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
|
@ -358,8 +376,12 @@ func (c *Client) EmbedHTTPClient(hc *http.Client) {
|
||||||
func (c *Client) log(e ErrEntry) {
|
func (c *Client) log(e ErrEntry) {
|
||||||
if c.KeepLog {
|
if c.KeepLog {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
c.ErrLog = append(c.ErrLog, e)
|
c.ErrLog = append(c.ErrLog, e)
|
||||||
c.Unlock()
|
} else if c.LogHook != nil {
|
||||||
|
// NOTE: There is a possibility that Log Printing hook slows it down.
|
||||||
|
// but the consumer can always do the Job in a go-routine.
|
||||||
|
c.LogHook(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||||
|
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
|
*/
|
||||||
|
|
||||||
|
package assert
|
||||||
|
|
||||||
|
import (
|
||||||
|
http "net/http"
|
||||||
|
url "net/url"
|
||||||
|
time "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Conditionf uses a Comparison to assert a complex condition.
|
||||||
|
func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
|
||||||
|
return Condition(t, comp, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Containsf asserts that the specified string, list(array, slice...) or map contains the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
|
||||||
|
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
|
||||||
|
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// assert.Emptyf(t, obj, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Empty(t, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equalf asserts that two objects are equal.
|
||||||
|
//
|
||||||
|
// assert.Equalf(t, 123, 123, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
//
|
||||||
|
// Pointer variable equality is determined based on the equality of the
|
||||||
|
// referenced values (as opposed to the memory addresses). Function equality
|
||||||
|
// cannot be determined and will always fail.
|
||||||
|
func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that it is equal to the provided error.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
|
||||||
|
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
|
// and equal.
|
||||||
|
//
|
||||||
|
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf asserts that a function returned an error (i.e. not `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if assert.Errorf(t, err, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, expectedErrorf, err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||||
|
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exactlyf asserts that two objects are equal is value and type.
|
||||||
|
//
|
||||||
|
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failf reports a failure through
|
||||||
|
func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||||
|
return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FailNowf fails test
|
||||||
|
func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||||
|
return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Falsef asserts that the specified value is false.
|
||||||
|
//
|
||||||
|
// assert.Falsef(t, myBool, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||||
|
return False(t, value, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||||
|
// body that contains a string.
|
||||||
|
//
|
||||||
|
// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyContains(t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||||
|
// body that does not contain a string.
|
||||||
|
//
|
||||||
|
// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyNotContains(t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPErrorf asserts that a specified handler returns an error status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||||
|
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPError(t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||||
|
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPRedirect(t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPSuccessf asserts that a specified handler returns a success status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPSuccess(t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
|
//
|
||||||
|
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||||
|
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||||
|
//
|
||||||
|
// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||||
|
return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||||
|
func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||||
|
return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||||
|
return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||||
|
func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||||
|
return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTypef asserts that the specified objects are of the same type.
|
||||||
|
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONEqf asserts that two JSON strings are equivalent.
|
||||||
|
//
|
||||||
|
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
|
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lenf asserts that the specified object has specific length.
|
||||||
|
// Lenf also fails if the object has a type that len() not accept.
|
||||||
|
//
|
||||||
|
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
|
||||||
|
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nilf asserts that the specified object is nil.
|
||||||
|
//
|
||||||
|
// assert.Nilf(t, err, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Nil(t, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoErrorf asserts that a function returned no error (i.e. `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, expectedObj, actualObj)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||||
|
return NoError(t, err, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
|
||||||
|
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||||
|
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, "two", obj[1])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEqualf asserts that the specified values are NOT equal.
|
||||||
|
//
|
||||||
|
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
//
|
||||||
|
// Pointer variable equality is determined based on the equality of the
|
||||||
|
// referenced values (as opposed to the memory addresses).
|
||||||
|
func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotNilf asserts that the specified object is not nil.
|
||||||
|
//
|
||||||
|
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotNil(t, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||||
|
//
|
||||||
|
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return NotPanics(t, f, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
|
//
|
||||||
|
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||||
|
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||||
|
func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotZero(t, i, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||||
|
//
|
||||||
|
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return Panics(t, f, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
|
||||||
|
// the recovered panic value equals the expected panic value.
|
||||||
|
//
|
||||||
|
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
|
//
|
||||||
|
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||||
|
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truef asserts that the specified value is true.
|
||||||
|
//
|
||||||
|
// assert.Truef(t, myBool, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||||
|
return True(t, value, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||||
|
//
|
||||||
|
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||||
|
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||||
|
func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Zero(t, i, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{.CommentFormat}}
|
||||||
|
func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
|
||||||
|
return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
|
||||||
|
}
|
|
@ -16,18 +16,35 @@ func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool
|
||||||
return Condition(a.t, comp, msgAndArgs...)
|
return Condition(a.t, comp, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditionf uses a Comparison to assert a complex condition.
|
||||||
|
func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
|
||||||
|
return Conditionf(a.t, comp, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
|
// a.Contains("Hello World", "World")
|
||||||
// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
|
// a.Contains(["Hello", "World"], "World")
|
||||||
// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
|
// a.Contains({"Hello": "World"}, "Hello")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Contains(a.t, s, contains, msgAndArgs...)
|
return Contains(a.t, s, contains, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Containsf asserts that the specified string, list(array, slice...) or map contains the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// a.Containsf("Hello World", "World", "error message %s", "formatted")
|
||||||
|
// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
|
||||||
|
// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Containsf(a.t, s, contains, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
@ -38,14 +55,25 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Empty(a.t, object, msgAndArgs...)
|
return Empty(a.t, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// a.Emptyf(obj, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Emptyf(a.t, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Equal asserts that two objects are equal.
|
// Equal asserts that two objects are equal.
|
||||||
//
|
//
|
||||||
// a.Equal(123, 123, "123 and 123 should be equal")
|
// a.Equal(123, 123)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
//
|
//
|
||||||
// Pointer variable equality is determined based on the equality of the
|
// Pointer variable equality is determined based on the equality of the
|
||||||
// referenced values (as opposed to the memory addresses).
|
// referenced values (as opposed to the memory addresses). Function equality
|
||||||
|
// cannot be determined and will always fail.
|
||||||
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Equal(a.t, expected, actual, msgAndArgs...)
|
return Equal(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
@ -54,28 +82,62 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
|
||||||
// and that it is equal to the provided error.
|
// and that it is equal to the provided error.
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// a.EqualError(err, expectedErrorString, "An error was expected")
|
// a.EqualError(err, expectedErrorString)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||||
return EqualError(a.t, theError, errString, msgAndArgs...)
|
return EqualError(a.t, theError, errString, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that it is equal to the provided error.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
|
||||||
|
return EqualErrorf(a.t, theError, errString, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
|
// a.EqualValues(uint32(123), int32(123))
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
|
// and equal.
|
||||||
|
//
|
||||||
|
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return EqualValuesf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equalf asserts that two objects are equal.
|
||||||
|
//
|
||||||
|
// a.Equalf(123, 123, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
//
|
||||||
|
// Pointer variable equality is determined based on the equality of the
|
||||||
|
// referenced values (as opposed to the memory addresses). Function equality
|
||||||
|
// cannot be determined and will always fail.
|
||||||
|
func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Equalf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Error asserts that a function returned an error (i.e. not `nil`).
|
// Error asserts that a function returned an error (i.e. not `nil`).
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// if a.Error(err, "An error was expected") {
|
// if a.Error(err) {
|
||||||
// assert.Equal(t, err, expectedError)
|
// assert.Equal(t, expectedError, err)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
@ -83,15 +145,36 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||||
return Error(a.t, err, msgAndArgs...)
|
return Error(a.t, err, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Errorf asserts that a function returned an error (i.e. not `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if a.Errorf(err, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, expectedErrorf, err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
|
||||||
|
return Errorf(a.t, err, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Exactly asserts that two objects are equal is value and type.
|
// Exactly asserts that two objects are equal is value and type.
|
||||||
//
|
//
|
||||||
// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
|
// a.Exactly(int32(123), int64(123))
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Exactly(a.t, expected, actual, msgAndArgs...)
|
return Exactly(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exactlyf asserts that two objects are equal is value and type.
|
||||||
|
//
|
||||||
|
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Exactlyf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Fail reports a failure through
|
// Fail reports a failure through
|
||||||
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
return Fail(a.t, failureMessage, msgAndArgs...)
|
return Fail(a.t, failureMessage, msgAndArgs...)
|
||||||
|
@ -102,15 +185,34 @@ func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) b
|
||||||
return FailNow(a.t, failureMessage, msgAndArgs...)
|
return FailNow(a.t, failureMessage, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FailNowf fails test
|
||||||
|
func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
|
||||||
|
return FailNowf(a.t, failureMessage, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failf reports a failure through
|
||||||
|
func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
|
||||||
|
return Failf(a.t, failureMessage, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// False asserts that the specified value is false.
|
// False asserts that the specified value is false.
|
||||||
//
|
//
|
||||||
// a.False(myBool, "myBool should be false")
|
// a.False(myBool)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
||||||
return False(a.t, value, msgAndArgs...)
|
return False(a.t, value, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Falsef asserts that the specified value is false.
|
||||||
|
//
|
||||||
|
// a.Falsef(myBool, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
|
||||||
|
return Falsef(a.t, value, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBodyContains asserts that a specified handler returns a
|
// HTTPBodyContains asserts that a specified handler returns a
|
||||||
// body that contains a string.
|
// body that contains a string.
|
||||||
//
|
//
|
||||||
|
@ -121,6 +223,16 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u
|
||||||
return HTTPBodyContains(a.t, handler, method, url, values, str)
|
return HTTPBodyContains(a.t, handler, method, url, values, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||||
|
// body that contains a string.
|
||||||
|
//
|
||||||
|
// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyContainsf(a.t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||||
// body that does not contain a string.
|
// body that does not contain a string.
|
||||||
//
|
//
|
||||||
|
@ -131,6 +243,16 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string
|
||||||
return HTTPBodyNotContains(a.t, handler, method, url, values, str)
|
return HTTPBodyNotContains(a.t, handler, method, url, values, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||||
|
// body that does not contain a string.
|
||||||
|
//
|
||||||
|
// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyNotContainsf(a.t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPError asserts that a specified handler returns an error status code.
|
// HTTPError asserts that a specified handler returns an error status code.
|
||||||
//
|
//
|
||||||
// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
@ -140,6 +262,15 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
||||||
return HTTPError(a.t, handler, method, url, values)
|
return HTTPError(a.t, handler, method, url, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPErrorf asserts that a specified handler returns an error status code.
|
||||||
|
//
|
||||||
|
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||||
|
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPErrorf(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
||||||
//
|
//
|
||||||
// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
@ -149,6 +280,15 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
||||||
return HTTPRedirect(a.t, handler, method, url, values)
|
return HTTPRedirect(a.t, handler, method, url, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
|
||||||
|
//
|
||||||
|
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||||
|
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPRedirectf(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
//
|
//
|
||||||
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
||||||
|
@ -158,13 +298,29 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st
|
||||||
return HTTPSuccess(a.t, handler, method, url, values)
|
return HTTPSuccess(a.t, handler, method, url, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPSuccessf asserts that a specified handler returns a success status code.
|
||||||
|
//
|
||||||
|
// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPSuccessf(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
// Implements asserts that an object is implemented by the specified interface.
|
// Implements asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
|
// a.Implements((*MyInterface)(nil), new(MyObject))
|
||||||
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
|
//
|
||||||
|
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||||
|
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Implementsf(a.t, interfaceObject, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// InDelta asserts that the two numerals are within delta of each other.
|
// InDelta asserts that the two numerals are within delta of each other.
|
||||||
//
|
//
|
||||||
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
||||||
|
@ -179,6 +335,20 @@ func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delt
|
||||||
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||||
|
func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||||
|
return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||||
|
//
|
||||||
|
// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||||
|
return InDeltaf(a.t, expected, actual, delta, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
@ -191,11 +361,28 @@ func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, ep
|
||||||
return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
|
return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||||
|
func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||||
|
return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||||
|
return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// IsType asserts that the specified objects are of the same type.
|
// IsType asserts that the specified objects are of the same type.
|
||||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return IsType(a.t, expectedType, object, msgAndArgs...)
|
return IsType(a.t, expectedType, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsTypef asserts that the specified objects are of the same type.
|
||||||
|
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return IsTypef(a.t, expectedType, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// JSONEq asserts that two JSON strings are equivalent.
|
// JSONEq asserts that two JSON strings are equivalent.
|
||||||
//
|
//
|
||||||
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||||
|
@ -205,30 +392,58 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf
|
||||||
return JSONEq(a.t, expected, actual, msgAndArgs...)
|
return JSONEq(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONEqf asserts that two JSON strings are equivalent.
|
||||||
|
//
|
||||||
|
// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
|
return JSONEqf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Len asserts that the specified object has specific length.
|
// Len asserts that the specified object has specific length.
|
||||||
// Len also fails if the object has a type that len() not accept.
|
// Len also fails if the object has a type that len() not accept.
|
||||||
//
|
//
|
||||||
// a.Len(mySlice, 3, "The size of slice is not 3")
|
// a.Len(mySlice, 3)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||||
return Len(a.t, object, length, msgAndArgs...)
|
return Len(a.t, object, length, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lenf asserts that the specified object has specific length.
|
||||||
|
// Lenf also fails if the object has a type that len() not accept.
|
||||||
|
//
|
||||||
|
// a.Lenf(mySlice, 3, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
|
||||||
|
return Lenf(a.t, object, length, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Nil asserts that the specified object is nil.
|
// Nil asserts that the specified object is nil.
|
||||||
//
|
//
|
||||||
// a.Nil(err, "err should be nothing")
|
// a.Nil(err)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Nil(a.t, object, msgAndArgs...)
|
return Nil(a.t, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nilf asserts that the specified object is nil.
|
||||||
|
//
|
||||||
|
// a.Nilf(err, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Nilf(a.t, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NoError asserts that a function returned no error (i.e. `nil`).
|
// NoError asserts that a function returned no error (i.e. `nil`).
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// if a.NoError(err) {
|
// if a.NoError(err) {
|
||||||
// assert.Equal(t, actualObj, expectedObj)
|
// assert.Equal(t, expectedObj, actualObj)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
@ -236,18 +451,42 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
||||||
return NoError(a.t, err, msgAndArgs...)
|
return NoError(a.t, err, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NoErrorf asserts that a function returned no error (i.e. `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if a.NoErrorf(err, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, expectedObj, actualObj)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
|
||||||
|
return NoErrorf(a.t, err, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
// a.NotContains("Hello World", "Earth")
|
||||||
// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
|
// a.NotContains(["Hello", "World"], "Earth")
|
||||||
// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
|
// a.NotContains({"Hello": "World"}, "Earth")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return NotContains(a.t, s, contains, msgAndArgs...)
|
return NotContains(a.t, s, contains, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
|
||||||
|
// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||||
|
// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotContainsf(a.t, s, contains, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
@ -260,9 +499,21 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo
|
||||||
return NotEmpty(a.t, object, msgAndArgs...)
|
return NotEmpty(a.t, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// if a.NotEmptyf(obj, "error message %s", "formatted") {
|
||||||
|
// assert.Equal(t, "two", obj[1])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotEmptyf(a.t, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEqual asserts that the specified values are NOT equal.
|
// NotEqual asserts that the specified values are NOT equal.
|
||||||
//
|
//
|
||||||
// a.NotEqual(obj1, obj2, "two objects shouldn't be equal")
|
// a.NotEqual(obj1, obj2)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
//
|
//
|
||||||
|
@ -272,26 +523,54 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
||||||
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualf asserts that the specified values are NOT equal.
|
||||||
|
//
|
||||||
|
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
//
|
||||||
|
// Pointer variable equality is determined based on the equality of the
|
||||||
|
// referenced values (as opposed to the memory addresses).
|
||||||
|
func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
// NotNil asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// a.NotNil(err, "err should be something")
|
// a.NotNil(err)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return NotNil(a.t, object, msgAndArgs...)
|
return NotNil(a.t, object, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotNilf asserts that the specified object is not nil.
|
||||||
|
//
|
||||||
|
// a.NotNilf(err, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotNilf(a.t, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||||
//
|
//
|
||||||
// a.NotPanics(func(){
|
// a.NotPanics(func(){ RemainCalm() })
|
||||||
// RemainCalm()
|
|
||||||
// }, "Calling RemainCalm() should NOT panic")
|
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
return NotPanics(a.t, f, msgAndArgs...)
|
return NotPanics(a.t, f, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||||
|
//
|
||||||
|
// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return NotPanicsf(a.t, f, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotRegexp asserts that a specified regexp does not match a string.
|
// NotRegexp asserts that a specified regexp does not match a string.
|
||||||
//
|
//
|
||||||
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
||||||
|
@ -302,22 +581,84 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
||||||
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
|
//
|
||||||
|
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||||
|
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotRegexpf(a.t, rx, str, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotSubsetf(a.t, list, subset, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||||
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return NotZero(a.t, i, msgAndArgs...)
|
return NotZero(a.t, i, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||||
|
func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return NotZerof(a.t, i, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||||
//
|
//
|
||||||
// a.Panics(func(){
|
// a.Panics(func(){ GoCrazy() })
|
||||||
// GoCrazy()
|
|
||||||
// }, "Calling GoCrazy() should panic")
|
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
return Panics(a.t, f, msgAndArgs...)
|
return Panics(a.t, f, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
|
||||||
|
// the recovered panic value equals the expected panic value.
|
||||||
|
//
|
||||||
|
// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
return PanicsWithValue(a.t, expected, f, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
|
||||||
|
// the recovered panic value equals the expected panic value.
|
||||||
|
//
|
||||||
|
// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return PanicsWithValuef(a.t, expected, f, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||||
|
//
|
||||||
|
// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||||
|
return Panicsf(a.t, f, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Regexp asserts that a specified regexp matches a string.
|
// Regexp asserts that a specified regexp matches a string.
|
||||||
//
|
//
|
||||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||||
|
@ -328,25 +669,78 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
||||||
return Regexp(a.t, rx, str, msgAndArgs...)
|
return Regexp(a.t, rx, str, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
|
//
|
||||||
|
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||||
|
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Regexpf(a.t, rx, str, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Subset(a.t, list, subset, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Subsetf(a.t, list, subset, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// True asserts that the specified value is true.
|
// True asserts that the specified value is true.
|
||||||
//
|
//
|
||||||
// a.True(myBool, "myBool should be true")
|
// a.True(myBool)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
||||||
return True(a.t, value, msgAndArgs...)
|
return True(a.t, value, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truef asserts that the specified value is true.
|
||||||
|
//
|
||||||
|
// a.Truef(myBool, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
|
||||||
|
return Truef(a.t, value, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// WithinDuration asserts that the two times are within duration delta of each other.
|
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||||
//
|
//
|
||||||
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
|
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||||
|
//
|
||||||
|
// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||||
|
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Zero asserts that i is the zero value for its type and returns the truth.
|
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||||
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Zero(a.t, i, msgAndArgs...)
|
return Zero(a.t, i, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||||
|
func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
|
||||||
|
return Zerof(a.t, i, msg, args...)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -18,6 +19,8 @@ import (
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
|
||||||
|
|
||||||
// TestingT is an interface wrapper around *testing.T
|
// TestingT is an interface wrapper around *testing.T
|
||||||
type TestingT interface {
|
type TestingT interface {
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...interface{})
|
||||||
|
@ -38,7 +41,15 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
|
||||||
if expected == nil || actual == nil {
|
if expected == nil || actual == nil {
|
||||||
return expected == actual
|
return expected == actual
|
||||||
}
|
}
|
||||||
|
if exp, ok := expected.([]byte); ok {
|
||||||
|
act, ok := actual.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
} else if exp == nil || act == nil {
|
||||||
|
return exp == nil && act == nil
|
||||||
|
}
|
||||||
|
return bytes.Equal(exp, act)
|
||||||
|
}
|
||||||
return reflect.DeepEqual(expected, actual)
|
return reflect.DeepEqual(expected, actual)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -108,11 +119,13 @@ func CallerInfo() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(file, "/")
|
parts := strings.Split(file, "/")
|
||||||
dir := parts[len(parts)-2]
|
|
||||||
file = parts[len(parts)-1]
|
file = parts[len(parts)-1]
|
||||||
|
if len(parts) > 1 {
|
||||||
|
dir := parts[len(parts)-2]
|
||||||
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
|
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
|
||||||
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Drop the package
|
// Drop the package
|
||||||
segments := strings.Split(name, ".")
|
segments := strings.Split(name, ".")
|
||||||
|
@ -181,7 +194,7 @@ func indentMessageLines(message string, longestLabelLen int) string {
|
||||||
// no need to align first line because it starts at the correct location (after the label)
|
// no need to align first line because it starts at the correct location (after the label)
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
|
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
|
||||||
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen +1) + "\t")
|
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||||
}
|
}
|
||||||
outBuf.WriteString(scanner.Text())
|
outBuf.WriteString(scanner.Text())
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
content = append(content, labeledContent{"Messages", message})
|
content = append(content, labeledContent{"Messages", message})
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Errorf("\r" + getWhitespaceString() + labeledOutput(content...))
|
t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -258,7 +271,7 @@ func labeledOutput(content ...labeledContent) string {
|
||||||
|
|
||||||
// Implements asserts that an object is implemented by the specified interface.
|
// Implements asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
|
// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
|
||||||
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||||
|
@ -283,20 +296,25 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
|
||||||
|
|
||||||
// Equal asserts that two objects are equal.
|
// Equal asserts that two objects are equal.
|
||||||
//
|
//
|
||||||
// assert.Equal(t, 123, 123, "123 and 123 should be equal")
|
// assert.Equal(t, 123, 123)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
//
|
//
|
||||||
// Pointer variable equality is determined based on the equality of the
|
// Pointer variable equality is determined based on the equality of the
|
||||||
// referenced values (as opposed to the memory addresses).
|
// referenced values (as opposed to the memory addresses). Function equality
|
||||||
|
// cannot be determined and will always fail.
|
||||||
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if err := validateEqualArgs(expected, actual); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
|
||||||
|
expected, actual, err), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
if !ObjectsAreEqual(expected, actual) {
|
if !ObjectsAreEqual(expected, actual) {
|
||||||
diff := diff(expected, actual)
|
diff := diff(expected, actual)
|
||||||
expected, actual = formatUnequalValues(expected, actual)
|
expected, actual = formatUnequalValues(expected, actual)
|
||||||
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
||||||
"expected: %s\n"+
|
"expected: %s\n"+
|
||||||
"received: %s%s", expected, actual, diff), msgAndArgs...)
|
"actual: %s%s", expected, actual, diff), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -322,7 +340,7 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
|
// assert.EqualValues(t, uint32(123), int32(123))
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -332,7 +350,7 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
|
||||||
expected, actual = formatUnequalValues(expected, actual)
|
expected, actual = formatUnequalValues(expected, actual)
|
||||||
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
||||||
"expected: %s\n"+
|
"expected: %s\n"+
|
||||||
"received: %s%s", expected, actual, diff), msgAndArgs...)
|
"actual: %s%s", expected, actual, diff), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -341,7 +359,7 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
|
||||||
|
|
||||||
// Exactly asserts that two objects are equal is value and type.
|
// Exactly asserts that two objects are equal is value and type.
|
||||||
//
|
//
|
||||||
// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
|
// assert.Exactly(t, int32(123), int64(123))
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -359,7 +377,7 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
// NotNil asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// assert.NotNil(t, err, "err should be something")
|
// assert.NotNil(t, err)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -386,7 +404,7 @@ func isNil(object interface{}) bool {
|
||||||
|
|
||||||
// Nil asserts that the specified object is nil.
|
// Nil asserts that the specified object is nil.
|
||||||
//
|
//
|
||||||
// assert.Nil(t, err, "err should be nothing")
|
// assert.Nil(t, err)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -431,9 +449,7 @@ func isEmpty(object interface{}) bool {
|
||||||
objValue := reflect.ValueOf(object)
|
objValue := reflect.ValueOf(object)
|
||||||
|
|
||||||
switch objValue.Kind() {
|
switch objValue.Kind() {
|
||||||
case reflect.Map:
|
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
|
||||||
fallthrough
|
|
||||||
case reflect.Slice, reflect.Chan:
|
|
||||||
{
|
{
|
||||||
return (objValue.Len() == 0)
|
return (objValue.Len() == 0)
|
||||||
}
|
}
|
||||||
|
@ -509,7 +525,7 @@ func getLen(x interface{}) (ok bool, length int) {
|
||||||
// Len asserts that the specified object has specific length.
|
// Len asserts that the specified object has specific length.
|
||||||
// Len also fails if the object has a type that len() not accept.
|
// Len also fails if the object has a type that len() not accept.
|
||||||
//
|
//
|
||||||
// assert.Len(t, mySlice, 3, "The size of slice is not 3")
|
// assert.Len(t, mySlice, 3)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
|
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -526,7 +542,7 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
||||||
|
|
||||||
// True asserts that the specified value is true.
|
// True asserts that the specified value is true.
|
||||||
//
|
//
|
||||||
// assert.True(t, myBool, "myBool should be true")
|
// assert.True(t, myBool)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -541,7 +557,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
// False asserts that the specified value is false.
|
// False asserts that the specified value is false.
|
||||||
//
|
//
|
||||||
// assert.False(t, myBool, "myBool should be false")
|
// assert.False(t, myBool)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -556,13 +572,17 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
// NotEqual asserts that the specified values are NOT equal.
|
// NotEqual asserts that the specified values are NOT equal.
|
||||||
//
|
//
|
||||||
// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
|
// assert.NotEqual(t, obj1, obj2)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
//
|
//
|
||||||
// Pointer variable equality is determined based on the equality of the
|
// Pointer variable equality is determined based on the equality of the
|
||||||
// referenced values (as opposed to the memory addresses).
|
// referenced values (as opposed to the memory addresses).
|
||||||
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if err := validateEqualArgs(expected, actual); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
|
||||||
|
expected, actual, err), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
if ObjectsAreEqual(expected, actual) {
|
if ObjectsAreEqual(expected, actual) {
|
||||||
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
|
||||||
|
@ -613,9 +633,9 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
|
// assert.Contains(t, "Hello World", "World")
|
||||||
// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
|
// assert.Contains(t, ["Hello", "World"], "World")
|
||||||
// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
|
// assert.Contains(t, {"Hello": "World"}, "Hello")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -635,9 +655,9 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
||||||
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
// assert.NotContains(t, "Hello World", "Earth")
|
||||||
// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
|
// assert.NotContains(t, ["Hello", "World"], "Earth")
|
||||||
// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
|
// assert.NotContains(t, {"Hello": "World"}, "Earth")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -654,6 +674,92 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
|
if subset == nil {
|
||||||
|
return true // we consider nil to be equal to the nil set
|
||||||
|
}
|
||||||
|
|
||||||
|
subsetValue := reflect.ValueOf(subset)
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
listKind := reflect.TypeOf(list).Kind()
|
||||||
|
subsetKind := reflect.TypeOf(subset).Kind()
|
||||||
|
|
||||||
|
if listKind != reflect.Array && listKind != reflect.Slice {
|
||||||
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
|
||||||
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < subsetValue.Len(); i++ {
|
||||||
|
element := subsetValue.Index(i).Interface()
|
||||||
|
ok, found := includeElement(list, element)
|
||||||
|
if !ok {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||||
|
// elements given in the specified subset(array, slice...).
|
||||||
|
//
|
||||||
|
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
|
if subset == nil {
|
||||||
|
return false // we consider nil to be equal to the nil set
|
||||||
|
}
|
||||||
|
|
||||||
|
subsetValue := reflect.ValueOf(subset)
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
listKind := reflect.TypeOf(list).Kind()
|
||||||
|
subsetKind := reflect.TypeOf(subset).Kind()
|
||||||
|
|
||||||
|
if listKind != reflect.Array && listKind != reflect.Slice {
|
||||||
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
|
||||||
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < subsetValue.Len(); i++ {
|
||||||
|
element := subsetValue.Index(i).Interface()
|
||||||
|
ok, found := includeElement(list, element)
|
||||||
|
if !ok {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
// Condition uses a Comparison to assert a complex condition.
|
// Condition uses a Comparison to assert a complex condition.
|
||||||
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
||||||
result := comp()
|
result := comp()
|
||||||
|
@ -691,9 +797,7 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
|
||||||
|
|
||||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||||
//
|
//
|
||||||
// assert.Panics(t, func(){
|
// assert.Panics(t, func(){ GoCrazy() })
|
||||||
// GoCrazy()
|
|
||||||
// }, "Calling GoCrazy() should panic")
|
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -705,11 +809,28 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
|
||||||
|
// the recovered panic value equals the expected panic value.
|
||||||
|
//
|
||||||
|
// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
|
funcDidPanic, panicValue := didPanic(f)
|
||||||
|
if !funcDidPanic {
|
||||||
|
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||||
|
}
|
||||||
|
if panicValue != expected {
|
||||||
|
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||||
//
|
//
|
||||||
// assert.NotPanics(t, func(){
|
// assert.NotPanics(t, func(){ RemainCalm() })
|
||||||
// RemainCalm()
|
|
||||||
// }, "Calling RemainCalm() should NOT panic")
|
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -723,7 +844,7 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
// WithinDuration asserts that the two times are within duration delta of each other.
|
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||||
//
|
//
|
||||||
// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
|
// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -763,6 +884,8 @@ func toFloat(x interface{}) (float64, bool) {
|
||||||
xf = float64(xn)
|
xf = float64(xn)
|
||||||
case float64:
|
case float64:
|
||||||
xf = float64(xn)
|
xf = float64(xn)
|
||||||
|
case time.Duration:
|
||||||
|
xf = float64(xn)
|
||||||
default:
|
default:
|
||||||
xok = false
|
xok = false
|
||||||
}
|
}
|
||||||
|
@ -785,7 +908,7 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
if math.IsNaN(af) {
|
if math.IsNaN(af) {
|
||||||
return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if math.IsNaN(bf) {
|
if math.IsNaN(bf) {
|
||||||
|
@ -812,7 +935,7 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
||||||
expectedSlice := reflect.ValueOf(expected)
|
expectedSlice := reflect.ValueOf(expected)
|
||||||
|
|
||||||
for i := 0; i < actualSlice.Len(); i++ {
|
for i := 0; i < actualSlice.Len(); i++ {
|
||||||
result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
|
result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
|
||||||
if !result {
|
if !result {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -831,7 +954,7 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
||||||
}
|
}
|
||||||
bf, bok := toFloat(actual)
|
bf, bok := toFloat(actual)
|
||||||
if !bok {
|
if !bok {
|
||||||
return 0, fmt.Errorf("expected value %q cannot be converted to float", actual)
|
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
return math.Abs(af-bf) / math.Abs(af), nil
|
return math.Abs(af-bf) / math.Abs(af), nil
|
||||||
|
@ -847,7 +970,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
||||||
}
|
}
|
||||||
if actualEpsilon > epsilon {
|
if actualEpsilon > epsilon {
|
||||||
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
|
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
|
||||||
" < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...)
|
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -882,7 +1005,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// if assert.NoError(t, err) {
|
// if assert.NoError(t, err) {
|
||||||
// assert.Equal(t, actualObj, expectedObj)
|
// assert.Equal(t, expectedObj, actualObj)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
@ -897,8 +1020,8 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||||
// Error asserts that a function returned an error (i.e. not `nil`).
|
// Error asserts that a function returned an error (i.e. not `nil`).
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// if assert.Error(t, err, "An error was expected") {
|
// if assert.Error(t, err) {
|
||||||
// assert.Equal(t, err, expectedError)
|
// assert.Equal(t, expectedError, err)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
@ -915,7 +1038,7 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||||
// and that it is equal to the provided error.
|
// and that it is equal to the provided error.
|
||||||
//
|
//
|
||||||
// actualObj, err := SomeFunction()
|
// actualObj, err := SomeFunction()
|
||||||
// assert.EqualError(t, err, expectedErrorString, "An error was expected")
|
// assert.EqualError(t, err, expectedErrorString)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
|
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||||
|
@ -928,7 +1051,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
return Fail(t, fmt.Sprintf("Error message not equal:\n"+
|
return Fail(t, fmt.Sprintf("Error message not equal:\n"+
|
||||||
"expected: %q\n"+
|
"expected: %q\n"+
|
||||||
"received: %q", expected, actual), msgAndArgs...)
|
"actual: %q", expected, actual), msgAndArgs...)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1061,6 +1184,22 @@ func diff(expected interface{}, actual interface{}) string {
|
||||||
return "\n\nDiff:\n" + diff
|
return "\n\nDiff:\n" + diff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateEqualArgs checks whether provided arguments can be safely used in the
|
||||||
|
// Equal/NotEqual functions.
|
||||||
|
func validateEqualArgs(expected, actual interface{}) error {
|
||||||
|
if isFunction(expected) || isFunction(actual) {
|
||||||
|
return errors.New("cannot take func type as argument")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFunction(arg interface{}) bool {
|
||||||
|
if arg == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return reflect.TypeOf(arg).Kind() == reflect.Func
|
||||||
|
}
|
||||||
|
|
||||||
var spewConfig = spew.ConfigState{
|
var spewConfig = spew.ConfigState{
|
||||||
Indent: " ",
|
Indent: " ",
|
||||||
DisablePointerAddresses: true,
|
DisablePointerAddresses: true,
|
||||||
|
|
|
@ -13,4 +13,4 @@ func New(t TestingT) *Assertions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl
|
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs
|
||||||
|
|
|
@ -8,16 +8,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// httpCode is a helper that returns HTTP code of the response. It returns -1
|
// httpCode is a helper that returns HTTP code of the response. It returns -1 and
|
||||||
// if building a new request fails.
|
// an error if building a new request fails.
|
||||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
|
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1
|
return -1, err
|
||||||
}
|
}
|
||||||
handler(w, req)
|
handler(w, req)
|
||||||
return w.Code
|
return w.Code, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
|
@ -26,11 +26,18 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) i
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if err != nil {
|
||||||
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return code >= http.StatusOK && code <= http.StatusPartialContent
|
|
||||||
|
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
||||||
|
if !isSuccessCode {
|
||||||
|
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSuccessCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
||||||
|
@ -39,11 +46,18 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if err != nil {
|
||||||
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
|
||||||
|
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
||||||
|
if !isRedirectCode {
|
||||||
|
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||||
|
}
|
||||||
|
|
||||||
|
return isRedirectCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPError asserts that a specified handler returns an error status code.
|
// HTTPError asserts that a specified handler returns an error status code.
|
||||||
|
@ -52,11 +66,18 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if err != nil {
|
||||||
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return code >= http.StatusBadRequest
|
|
||||||
|
isErrorCode := code >= http.StatusBadRequest
|
||||||
|
if !isErrorCode {
|
||||||
|
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||||
|
}
|
||||||
|
|
||||||
|
return isErrorCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
Jean-loup Gailly Mark Adler
|
||||||
|
jloup@gzip.org madler@alumni.caltech.edu
|
|
@ -1,31 +1,10 @@
|
||||||
|
// Package crc32combine provides functionality to calculate the combined
|
||||||
|
// CRC-32 hash of two given CRC-32 hash values.
|
||||||
package crc32combine
|
package crc32combine
|
||||||
|
|
||||||
/*
|
// Ported from C to Go in 2016 by Justin Ruggles, with minimal alteration.
|
||||||
zlib CRC32 combine (https://github.com/madler/zlib)
|
// Used uint for unsigned long. Used uint32 for input arguments in order to match
|
||||||
|
// the Go hash/crc32 package. zlib CRC32 combine (https://github.com/madler/zlib)
|
||||||
Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler <madler@alumni.caltech.edu>
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
Ported from C to Go in 2016 by Justin Ruggles, with minimal alteration.
|
|
||||||
Used uint for unsigned long. Used uint32 for input arguments in order to match
|
|
||||||
the Go hash/crc32 package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
func gf2MatrixTimes(mat []uint, vec uint) uint {
|
func gf2MatrixTimes(mat []uint, vec uint) uint {
|
||||||
var sum uint
|
var sum uint
|
||||||
|
@ -46,59 +25,62 @@ func gf2MatrixSquare(square, mat []uint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRC32Combine returns the combined CRC-32 hash value of the two passed CRC-32
|
||||||
|
// hash values crc1 and crc2. poly represents the generator polynomial
|
||||||
|
// and len2 specifies the byte length that the crc2 hash covers.
|
||||||
func CRC32Combine(poly uint32, crc1, crc2 uint32, len2 int64) uint32 {
|
func CRC32Combine(poly uint32, crc1, crc2 uint32, len2 int64) uint32 {
|
||||||
/* degenerate case (also disallow negative lengths) */
|
// degenerate case (also disallow negative lengths)
|
||||||
if len2 <= 0 {
|
if len2 <= 0 {
|
||||||
return crc1
|
return crc1
|
||||||
}
|
}
|
||||||
|
|
||||||
even := make([]uint, 32) /* even-power-of-two zeros operator */
|
even := make([]uint, 32) // even-power-of-two zeros operator
|
||||||
odd := make([]uint, 32) /* odd-power-of-two zeros operator */
|
odd := make([]uint, 32) // odd-power-of-two zeros operator
|
||||||
|
|
||||||
/* put operator for one zero bit in odd */
|
// put operator for one zero bit in odd
|
||||||
odd[0] = uint(poly) /* CRC-32 polynomial */
|
odd[0] = uint(poly) // CRC-32 polynomial
|
||||||
row := uint(1)
|
row := uint(1)
|
||||||
for n := 1; n < 32; n++ {
|
for n := 1; n < 32; n++ {
|
||||||
odd[n] = row
|
odd[n] = row
|
||||||
row <<= 1
|
row <<= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put operator for two zero bits in even */
|
// put operator for two zero bits in even
|
||||||
gf2MatrixSquare(even, odd)
|
gf2MatrixSquare(even, odd)
|
||||||
|
|
||||||
/* put operator for four zero bits in odd */
|
// put operator for four zero bits in odd
|
||||||
gf2MatrixSquare(odd, even)
|
gf2MatrixSquare(odd, even)
|
||||||
|
|
||||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
// apply len2 zeros to crc1 (first square will put the operator for one
|
||||||
zero byte, eight zero bits, in even) */
|
// zero byte, eight zero bits, in even)
|
||||||
crc1n := uint(crc1)
|
crc1n := uint(crc1)
|
||||||
for {
|
for {
|
||||||
/* apply zeros operator for this bit of len2 */
|
// apply zeros operator for this bit of len2
|
||||||
gf2MatrixSquare(even, odd)
|
gf2MatrixSquare(even, odd)
|
||||||
if len2&1 != 0 {
|
if len2&1 != 0 {
|
||||||
crc1n = gf2MatrixTimes(even, crc1n)
|
crc1n = gf2MatrixTimes(even, crc1n)
|
||||||
}
|
}
|
||||||
len2 >>= 1
|
len2 >>= 1
|
||||||
|
|
||||||
/* if no more bits set, then done */
|
// if no more bits set, then done
|
||||||
if len2 == 0 {
|
if len2 == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
/* another iteration of the loop with odd and even swapped */
|
// another iteration of the loop with odd and even swapped
|
||||||
gf2MatrixSquare(odd, even)
|
gf2MatrixSquare(odd, even)
|
||||||
if len2&1 != 0 {
|
if len2&1 != 0 {
|
||||||
crc1n = gf2MatrixTimes(odd, crc1n)
|
crc1n = gf2MatrixTimes(odd, crc1n)
|
||||||
}
|
}
|
||||||
len2 >>= 1
|
len2 >>= 1
|
||||||
|
|
||||||
/* if no more bits set, then done */
|
// if no more bits set, then done
|
||||||
if len2 == 0 {
|
if len2 == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return combined crc */
|
// return combined crc
|
||||||
crc1n ^= uint(crc2)
|
crc1n ^= uint(crc2)
|
||||||
return uint32(crc1n)
|
return uint32(crc1n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google 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,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
|
@ -51,38 +51,6 @@ const (
|
||||||
maxNonces = 100
|
maxNonces = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
// CertOption is an optional argument type for Client methods which manipulate
|
|
||||||
// certificate data.
|
|
||||||
type CertOption interface {
|
|
||||||
privateCertOpt()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithKey creates an option holding a private/public key pair.
|
|
||||||
// The private part signs a certificate, and the public part represents the signee.
|
|
||||||
func WithKey(key crypto.Signer) CertOption {
|
|
||||||
return &certOptKey{key}
|
|
||||||
}
|
|
||||||
|
|
||||||
type certOptKey struct {
|
|
||||||
key crypto.Signer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*certOptKey) privateCertOpt() {}
|
|
||||||
|
|
||||||
// WithTemplate creates an option for specifying a certificate template.
|
|
||||||
// See x509.CreateCertificate for template usage details.
|
|
||||||
//
|
|
||||||
// In TLSSNIxChallengeCert methods, the template is also used as parent,
|
|
||||||
// resulting in a self-signed certificate.
|
|
||||||
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
|
|
||||||
func WithTemplate(t *x509.Certificate) CertOption {
|
|
||||||
return (*certOptTemplate)(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
type certOptTemplate x509.Certificate
|
|
||||||
|
|
||||||
func (*certOptTemplate) privateCertOpt() {}
|
|
||||||
|
|
||||||
// Client is an ACME client.
|
// Client is an ACME client.
|
||||||
// The only required field is Key. An example of creating a client with a new key
|
// The only required field is Key. An example of creating a client with a new key
|
||||||
// is as follows:
|
// is as follows:
|
||||||
|
@ -174,7 +142,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||||
//
|
//
|
||||||
// In the case where CA server does not provide the issued certificate in the response,
|
// In the case where CA server does not provide the issued certificate in the response,
|
||||||
// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
|
// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
|
||||||
// In such scenario the caller can cancel the polling with ctx.
|
// In such a scenario, the caller can cancel the polling with ctx.
|
||||||
//
|
//
|
||||||
// CreateCert returns an error if the CA's response or chain was unreasonably large.
|
// CreateCert returns an error if the CA's response or chain was unreasonably large.
|
||||||
// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
|
// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
|
||||||
|
@ -207,7 +175,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
||||||
return nil, "", responseError(res)
|
return nil, "", responseError(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
curl := res.Header.Get("location") // cert permanent URL
|
curl := res.Header.Get("Location") // cert permanent URL
|
||||||
if res.ContentLength == 0 {
|
if res.ContentLength == 0 {
|
||||||
// no cert in the body; poll until we get it
|
// no cert in the body; poll until we get it
|
||||||
cert, err := c.FetchCert(ctx, curl, bundle)
|
cert, err := c.FetchCert(ctx, curl, bundle)
|
||||||
|
@ -240,7 +208,7 @@ func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]by
|
||||||
if res.StatusCode > 299 {
|
if res.StatusCode > 299 {
|
||||||
return nil, responseError(res)
|
return nil, responseError(res)
|
||||||
}
|
}
|
||||||
d := retryAfter(res.Header.Get("retry-after"), 3*time.Second)
|
d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
|
||||||
select {
|
select {
|
||||||
case <-time.After(d):
|
case <-time.After(d):
|
||||||
// retry
|
// retry
|
||||||
|
@ -289,7 +257,7 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
|
||||||
func AcceptTOS(tosURL string) bool { return true }
|
func AcceptTOS(tosURL string) bool { return true }
|
||||||
|
|
||||||
// Register creates a new account registration by following the "new-reg" flow.
|
// Register creates a new account registration by following the "new-reg" flow.
|
||||||
// It returns registered account. The a argument is not modified.
|
// It returns the registered account. The account is not modified.
|
||||||
//
|
//
|
||||||
// The registration may require the caller to agree to the CA's Terms of Service (TOS).
|
// The registration may require the caller to agree to the CA's Terms of Service (TOS).
|
||||||
// If so, and the account has not indicated the acceptance of the terms (see Account for details),
|
// If so, and the account has not indicated the acceptance of the terms (see Account for details),
|
||||||
|
@ -444,7 +412,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
retry := res.Header.Get("retry-after")
|
retry := res.Header.Get("Retry-After")
|
||||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
if err := sleep(retry, 1); err != nil {
|
if err := sleep(retry, 1); err != nil {
|
||||||
|
@ -703,7 +671,7 @@ func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string
|
||||||
// clear any nonces that we might've stored that might now be
|
// clear any nonces that we might've stored that might now be
|
||||||
// considered bad
|
// considered bad
|
||||||
c.clearNonces()
|
c.clearNonces()
|
||||||
retry := res.Header.Get("retry-after")
|
retry := res.Header.Get("Retry-After")
|
||||||
if err := sleep(retry, 1); err != nil {
|
if err := sleep(retry, 1); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1027,6 +995,7 @@ func keyAuth(pub crypto.PublicKey, token string) (string, error) {
|
||||||
|
|
||||||
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
|
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
|
||||||
// with the given SANs and auto-generated public/private key pair.
|
// with the given SANs and auto-generated public/private key pair.
|
||||||
|
// The Subject Common Name is set to the first SAN to aid debugging.
|
||||||
// To create a cert with a custom key pair, specify WithKey option.
|
// To create a cert with a custom key pair, specify WithKey option.
|
||||||
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||||
var (
|
var (
|
||||||
|
@ -1065,6 +1034,9 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmpl.DNSNames = san
|
tmpl.DNSNames = san
|
||||||
|
if len(san) > 0 {
|
||||||
|
tmpl.Subject.CommonName = san[0]
|
||||||
|
}
|
||||||
|
|
||||||
der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
|
der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -33,6 +33,12 @@ import (
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// createCertRetryAfter is how much time to wait before removing a failed state
|
||||||
|
// entry due to an unsuccessful createCert call.
|
||||||
|
// This is a variable instead of a const for testing.
|
||||||
|
// TODO: Consider making it configurable or an exp backoff?
|
||||||
|
var createCertRetryAfter = time.Minute
|
||||||
|
|
||||||
// pseudoRand is safe for concurrent use.
|
// pseudoRand is safe for concurrent use.
|
||||||
var pseudoRand *lockedMathRand
|
var pseudoRand *lockedMathRand
|
||||||
|
|
||||||
|
@ -77,8 +83,10 @@ func defaultHostPolicy(context.Context, string) error {
|
||||||
// It obtains and refreshes certificates automatically,
|
// It obtains and refreshes certificates automatically,
|
||||||
// as well as providing them to a TLS server via tls.Config.
|
// as well as providing them to a TLS server via tls.Config.
|
||||||
//
|
//
|
||||||
// To preserve issued certificates and improve overall performance,
|
// You must specify a cache implementation, such as DirCache,
|
||||||
// use a cache implementation of Cache. For instance, DirCache.
|
// to reuse obtained certificates across program restarts.
|
||||||
|
// Otherwise your server is very likely to exceed the certificate
|
||||||
|
// issuer's request rate limits.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
// Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
|
// Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
|
||||||
// The registration may require the caller to agree to the CA's TOS.
|
// The registration may require the caller to agree to the CA's TOS.
|
||||||
|
@ -170,6 +178,12 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, errors.New("acme/autocert: missing server name")
|
return nil, errors.New("acme/autocert: missing server name")
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(strings.Trim(name, "."), ".") {
|
||||||
|
return nil, errors.New("acme/autocert: server name component count invalid")
|
||||||
|
}
|
||||||
|
if strings.ContainsAny(name, `/\`) {
|
||||||
|
return nil, errors.New("acme/autocert: server name contains invalid character")
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -357,12 +371,29 @@ func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certifica
|
||||||
|
|
||||||
// We are the first; state is locked.
|
// We are the first; state is locked.
|
||||||
// Unblock the readers when domain ownership is verified
|
// Unblock the readers when domain ownership is verified
|
||||||
// and the we got the cert or the process failed.
|
// and we got the cert or the process failed.
|
||||||
defer state.Unlock()
|
defer state.Unlock()
|
||||||
state.locked = false
|
state.locked = false
|
||||||
|
|
||||||
der, leaf, err := m.authorizedCert(ctx, state.key, domain)
|
der, leaf, err := m.authorizedCert(ctx, state.key, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Remove the failed state after some time,
|
||||||
|
// making the manager call createCert again on the following TLS hello.
|
||||||
|
time.AfterFunc(createCertRetryAfter, func() {
|
||||||
|
defer testDidRemoveState(domain)
|
||||||
|
m.stateMu.Lock()
|
||||||
|
defer m.stateMu.Unlock()
|
||||||
|
// Verify the state hasn't changed and it's still invalid
|
||||||
|
// before deleting.
|
||||||
|
s, ok := m.state[domain]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := validCert(domain, s.cert, s.key); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(m.state, domain)
|
||||||
|
})
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
state.cert = der
|
state.cert = der
|
||||||
|
@ -408,10 +439,9 @@ func (m *Manager) certState(domain string) (*certState, error) {
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorizedCert starts domain ownership verification process and requests a new cert upon success.
|
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
||||||
// The key argument is the certificate private key.
|
// The key argument is the certificate private key.
|
||||||
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
|
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
|
||||||
// TODO: make m.verify retry or retry m.verify calls here
|
|
||||||
if err := m.verify(ctx, domain); err != nil {
|
if err := m.verify(ctx, domain); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -782,5 +812,10 @@ func (r *lockedMathRand) int63n(max int64) int64 {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// for easier testing
|
// For easier testing.
|
||||||
var timeNow = time.Now
|
var (
|
||||||
|
timeNow = time.Now
|
||||||
|
|
||||||
|
// Called when a state is removed.
|
||||||
|
testDidRemoveState = func(domain string) {}
|
||||||
|
)
|
||||||
|
|
|
@ -36,6 +36,9 @@ import (
|
||||||
// operating system-specific cache or temp directory. This may not
|
// operating system-specific cache or temp directory. This may not
|
||||||
// be suitable for servers spanning multiple machines.
|
// be suitable for servers spanning multiple machines.
|
||||||
//
|
//
|
||||||
|
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||||
|
// should only be used with servers that support HTTP/2.
|
||||||
|
//
|
||||||
// The returned Listener also enables TCP keep-alives on the accepted
|
// The returned Listener also enables TCP keep-alives on the accepted
|
||||||
// connections. The returned *tls.Conn are returned before their TLS
|
// connections. The returned *tls.Conn are returned before their TLS
|
||||||
// handshake has completed.
|
// handshake has completed.
|
||||||
|
@ -58,6 +61,9 @@ func NewListener(domains ...string) net.Listener {
|
||||||
// Listener listens on the standard TLS port (443) on all interfaces
|
// Listener listens on the standard TLS port (443) on all interfaces
|
||||||
// and returns a net.Listener returning *tls.Conn connections.
|
// and returns a net.Listener returning *tls.Conn connections.
|
||||||
//
|
//
|
||||||
|
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||||
|
// should only be used with servers that support HTTP/2.
|
||||||
|
//
|
||||||
// The returned Listener also enables TCP keep-alives on the accepted
|
// The returned Listener also enables TCP keep-alives on the accepted
|
||||||
// connections. The returned *tls.Conn are returned before their TLS
|
// connections. The returned *tls.Conn are returned before their TLS
|
||||||
// handshake has completed.
|
// handshake has completed.
|
||||||
|
@ -69,6 +75,7 @@ func (m *Manager) Listener() net.Listener {
|
||||||
m: m,
|
m: m,
|
||||||
conf: &tls.Config{
|
conf: &tls.Config{
|
||||||
GetCertificate: m.GetCertificate, // bonus: panic on nil m
|
GetCertificate: m.GetCertificate, // bonus: panic on nil m
|
||||||
|
NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
|
ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -293,3 +295,35 @@ func (e *wireError) error(h http.Header) *Error {
|
||||||
Header: h,
|
Header: h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
|
||||||
|
// customizing a temporary certificate for TLS-SNI challenges.
|
||||||
|
type CertOption interface {
|
||||||
|
privateCertOpt()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithKey creates an option holding a private/public key pair.
|
||||||
|
// The private part signs a certificate, and the public part represents the signee.
|
||||||
|
func WithKey(key crypto.Signer) CertOption {
|
||||||
|
return &certOptKey{key}
|
||||||
|
}
|
||||||
|
|
||||||
|
type certOptKey struct {
|
||||||
|
key crypto.Signer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*certOptKey) privateCertOpt() {}
|
||||||
|
|
||||||
|
// WithTemplate creates an option for specifying a certificate template.
|
||||||
|
// See x509.CreateCertificate for template usage details.
|
||||||
|
//
|
||||||
|
// In TLSSNIxChallengeCert methods, the template is also used as parent,
|
||||||
|
// resulting in a self-signed certificate.
|
||||||
|
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
|
||||||
|
func WithTemplate(t *x509.Certificate) CertOption {
|
||||||
|
return (*certOptTemplate)(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
type certOptTemplate x509.Certificate
|
||||||
|
|
||||||
|
func (*certOptTemplate) privateCertOpt() {}
|
||||||
|
|
|
@ -17,40 +17,41 @@
|
||||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
"golang.org/x/sys/unix"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// State contains the state of a terminal.
|
// State contains the state of a terminal.
|
||||||
type State struct {
|
type State struct {
|
||||||
termios syscall.Termios
|
termios unix.Termios
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
func IsTerminal(fd int) bool {
|
func IsTerminal(fd int) bool {
|
||||||
var termios syscall.Termios
|
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
return err == nil
|
||||||
return err == 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||||
// mode and returns the previous state of the terminal so that it can be
|
// mode and returns the previous state of the terminal so that it can be
|
||||||
// restored.
|
// restored.
|
||||||
func MakeRaw(fd int) (*State, error) {
|
func MakeRaw(fd int) (*State, error) {
|
||||||
var oldState State
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := oldState.termios
|
oldState := State{termios: *termios}
|
||||||
|
|
||||||
// This attempts to replicate the behaviour documented for cfmakeraw in
|
// This attempts to replicate the behaviour documented for cfmakeraw in
|
||||||
// the termios(3) manpage.
|
// the termios(3) manpage.
|
||||||
newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
||||||
newState.Oflag &^= syscall.OPOST
|
termios.Oflag &^= unix.OPOST
|
||||||
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
||||||
newState.Cflag &^= syscall.CSIZE | syscall.PARENB
|
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
||||||
newState.Cflag |= syscall.CS8
|
termios.Cflag |= unix.CS8
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
termios.Cc[unix.VMIN] = 1
|
||||||
|
termios.Cc[unix.VTIME] = 0
|
||||||
|
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,59 +61,55 @@ func MakeRaw(fd int) (*State, error) {
|
||||||
// GetState returns the current state of a terminal which may be useful to
|
// GetState returns the current state of a terminal which may be useful to
|
||||||
// restore the terminal after a signal.
|
// restore the terminal after a signal.
|
||||||
func GetState(fd int) (*State, error) {
|
func GetState(fd int) (*State, error) {
|
||||||
var oldState State
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &oldState, nil
|
return &State{termios: *termios}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, state *State) error {
|
func Restore(fd int, state *State) error {
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 {
|
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
func GetSize(fd int) (width, height int, err error) {
|
func GetSize(fd int) (width, height int, err error) {
|
||||||
var dimensions [4]uint16
|
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
|
||||||
|
if err != nil {
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
|
|
||||||
return -1, -1, err
|
return -1, -1, err
|
||||||
}
|
}
|
||||||
return int(dimensions[1]), int(dimensions[0]), nil
|
return int(ws.Col), int(ws.Row), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
||||||
type passwordReader int
|
type passwordReader int
|
||||||
|
|
||||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||||
return syscall.Read(int(r), buf)
|
return unix.Read(int(r), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
// returned does not include the \n.
|
// returned does not include the \n.
|
||||||
func ReadPassword(fd int) ([]byte, error) {
|
func ReadPassword(fd int) ([]byte, error) {
|
||||||
var oldState syscall.Termios
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := oldState
|
newState := *termios
|
||||||
newState.Lflag &^= syscall.ECHO
|
newState.Lflag &^= unix.ECHO
|
||||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
newState.Lflag |= unix.ICANON | unix.ISIG
|
||||||
newState.Iflag |= syscall.ICRNL
|
newState.Iflag |= unix.ICRNL
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
|
unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return readPasswordLine(passwordReader(fd))
|
return readPasswordLine(passwordReader(fd))
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import "syscall"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TIOCGETA
|
const ioctlReadTermios = unix.TIOCGETA
|
||||||
const ioctlWriteTermios = syscall.TIOCSETA
|
const ioctlWriteTermios = unix.TIOCSETA
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
// These constants are declared here, rather than importing
|
import "golang.org/x/sys/unix"
|
||||||
// them from the syscall package as some syscall packages, even
|
|
||||||
// on linux, for example gccgo, do not declare them.
|
const ioctlReadTermios = unix.TCGETS
|
||||||
const ioctlReadTermios = 0x5401 // syscall.TCGETS
|
const ioctlWriteTermios = unix.TCSETS
|
||||||
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
|
|
||||||
|
|
|
@ -17,53 +17,7 @@
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
"golang.org/x/sys/windows"
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
enableLineInput = 2
|
|
||||||
enableEchoInput = 4
|
|
||||||
enableProcessedInput = 1
|
|
||||||
enableWindowInput = 8
|
|
||||||
enableMouseInput = 16
|
|
||||||
enableInsertMode = 32
|
|
||||||
enableQuickEditMode = 64
|
|
||||||
enableExtendedFlags = 128
|
|
||||||
enableAutoPosition = 256
|
|
||||||
enableProcessedOutput = 1
|
|
||||||
enableWrapAtEolOutput = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
|
||||||
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
|
||||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
short int16
|
|
||||||
word uint16
|
|
||||||
|
|
||||||
coord struct {
|
|
||||||
x short
|
|
||||||
y short
|
|
||||||
}
|
|
||||||
smallRect struct {
|
|
||||||
left short
|
|
||||||
top short
|
|
||||||
right short
|
|
||||||
bottom short
|
|
||||||
}
|
|
||||||
consoleScreenBufferInfo struct {
|
|
||||||
size coord
|
|
||||||
cursorPosition coord
|
|
||||||
attributes word
|
|
||||||
window smallRect
|
|
||||||
maximumWindowSize coord
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
|
@ -73,8 +27,8 @@ type State struct {
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
func IsTerminal(fd int) bool {
|
func IsTerminal(fd int) bool {
|
||||||
var st uint32
|
var st uint32
|
||||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
err := windows.GetConsoleMode(windows.Handle(fd), &st)
|
||||||
return r != 0 && e == 0
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||||
|
@ -82,14 +36,12 @@ func IsTerminal(fd int) bool {
|
||||||
// restored.
|
// restored.
|
||||||
func MakeRaw(fd int) (*State, error) {
|
func MakeRaw(fd int) (*State, error) {
|
||||||
var st uint32
|
var st uint32
|
||||||
_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
||||||
if e != 0 {
|
return nil, err
|
||||||
return nil, error(e)
|
|
||||||
}
|
}
|
||||||
raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
|
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
|
||||||
_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0)
|
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
|
||||||
if e != 0 {
|
return nil, err
|
||||||
return nil, error(e)
|
|
||||||
}
|
}
|
||||||
return &State{st}, nil
|
return &State{st}, nil
|
||||||
}
|
}
|
||||||
|
@ -98,9 +50,8 @@ func MakeRaw(fd int) (*State, error) {
|
||||||
// restore the terminal after a signal.
|
// restore the terminal after a signal.
|
||||||
func GetState(fd int) (*State, error) {
|
func GetState(fd int) (*State, error) {
|
||||||
var st uint32
|
var st uint32
|
||||||
_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
||||||
if e != 0 {
|
return nil, err
|
||||||
return nil, error(e)
|
|
||||||
}
|
}
|
||||||
return &State{st}, nil
|
return &State{st}, nil
|
||||||
}
|
}
|
||||||
|
@ -108,25 +59,23 @@ func GetState(fd int) (*State, error) {
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, state *State) error {
|
func Restore(fd int, state *State) error {
|
||||||
_, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0)
|
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
func GetSize(fd int) (width, height int, err error) {
|
func GetSize(fd int) (width, height int, err error) {
|
||||||
var info consoleScreenBufferInfo
|
var info windows.ConsoleScreenBufferInfo
|
||||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0)
|
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
|
||||||
if e != 0 {
|
return 0, 0, err
|
||||||
return 0, 0, error(e)
|
|
||||||
}
|
}
|
||||||
return int(info.size.x), int(info.size.y), nil
|
return int(info.Size.X), int(info.Size.Y), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
|
// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
|
||||||
type passwordReader int
|
type passwordReader int
|
||||||
|
|
||||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||||
return syscall.Read(syscall.Handle(r), buf)
|
return windows.Read(windows.Handle(r), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||||
|
@ -134,21 +83,19 @@ func (r passwordReader) Read(buf []byte) (int, error) {
|
||||||
// returned does not include the \n.
|
// returned does not include the \n.
|
||||||
func ReadPassword(fd int) ([]byte, error) {
|
func ReadPassword(fd int) ([]byte, error) {
|
||||||
var st uint32
|
var st uint32
|
||||||
_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
||||||
if e != 0 {
|
return nil, err
|
||||||
return nil, error(e)
|
|
||||||
}
|
}
|
||||||
old := st
|
old := st
|
||||||
|
|
||||||
st &^= (enableEchoInput)
|
st &^= (windows.ENABLE_ECHO_INPUT)
|
||||||
st |= (enableProcessedInput | enableLineInput | enableProcessedOutput)
|
st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
|
||||||
_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
|
if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
|
||||||
if e != 0 {
|
return nil, err
|
||||||
return nil, error(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
|
windows.SetConsoleMode(windows.Handle(fd), old)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return readPasswordLine(passwordReader(fd))
|
return readPasswordLine(passwordReader(fd))
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// Package context defines the Context type, which carries deadlines,
|
// Package context defines the Context type, which carries deadlines,
|
||||||
// cancelation signals, and other request-scoped values across API boundaries
|
// cancelation signals, and other request-scoped values across API boundaries
|
||||||
// and between processes.
|
// and between processes.
|
||||||
|
// As of Go 1.7 this package is available in the standard library under the
|
||||||
|
// name context. https://golang.org/pkg/context.
|
||||||
//
|
//
|
||||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
// Incoming requests to a server should create a Context, and outgoing calls to
|
||||||
// servers should accept a Context. The chain of function calls between must
|
// servers should accept a Context. The chain of function calls between must
|
||||||
|
@ -36,103 +38,6 @@
|
||||||
// Contexts.
|
// Contexts.
|
||||||
package context // import "golang.org/x/net/context"
|
package context // import "golang.org/x/net/context"
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// A Context carries a deadline, a cancelation signal, and other values across
|
|
||||||
// API boundaries.
|
|
||||||
//
|
|
||||||
// Context's methods may be called by multiple goroutines simultaneously.
|
|
||||||
type Context interface {
|
|
||||||
// Deadline returns the time when work done on behalf of this context
|
|
||||||
// should be canceled. Deadline returns ok==false when no deadline is
|
|
||||||
// set. Successive calls to Deadline return the same results.
|
|
||||||
Deadline() (deadline time.Time, ok bool)
|
|
||||||
|
|
||||||
// Done returns a channel that's closed when work done on behalf of this
|
|
||||||
// context should be canceled. Done may return nil if this context can
|
|
||||||
// never be canceled. Successive calls to Done return the same value.
|
|
||||||
//
|
|
||||||
// WithCancel arranges for Done to be closed when cancel is called;
|
|
||||||
// WithDeadline arranges for Done to be closed when the deadline
|
|
||||||
// expires; WithTimeout arranges for Done to be closed when the timeout
|
|
||||||
// elapses.
|
|
||||||
//
|
|
||||||
// Done is provided for use in select statements:
|
|
||||||
//
|
|
||||||
// // Stream generates values with DoSomething and sends them to out
|
|
||||||
// // until DoSomething returns an error or ctx.Done is closed.
|
|
||||||
// func Stream(ctx context.Context, out chan<- Value) error {
|
|
||||||
// for {
|
|
||||||
// v, err := DoSomething(ctx)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// select {
|
|
||||||
// case <-ctx.Done():
|
|
||||||
// return ctx.Err()
|
|
||||||
// case out <- v:
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// See http://blog.golang.org/pipelines for more examples of how to use
|
|
||||||
// a Done channel for cancelation.
|
|
||||||
Done() <-chan struct{}
|
|
||||||
|
|
||||||
// Err returns a non-nil error value after Done is closed. Err returns
|
|
||||||
// Canceled if the context was canceled or DeadlineExceeded if the
|
|
||||||
// context's deadline passed. No other values for Err are defined.
|
|
||||||
// After Done is closed, successive calls to Err return the same value.
|
|
||||||
Err() error
|
|
||||||
|
|
||||||
// Value returns the value associated with this context for key, or nil
|
|
||||||
// if no value is associated with key. Successive calls to Value with
|
|
||||||
// the same key returns the same result.
|
|
||||||
//
|
|
||||||
// Use context values only for request-scoped data that transits
|
|
||||||
// processes and API boundaries, not for passing optional parameters to
|
|
||||||
// functions.
|
|
||||||
//
|
|
||||||
// A key identifies a specific value in a Context. Functions that wish
|
|
||||||
// to store values in Context typically allocate a key in a global
|
|
||||||
// variable then use that key as the argument to context.WithValue and
|
|
||||||
// Context.Value. A key can be any type that supports equality;
|
|
||||||
// packages should define keys as an unexported type to avoid
|
|
||||||
// collisions.
|
|
||||||
//
|
|
||||||
// Packages that define a Context key should provide type-safe accessors
|
|
||||||
// for the values stores using that key:
|
|
||||||
//
|
|
||||||
// // Package user defines a User type that's stored in Contexts.
|
|
||||||
// package user
|
|
||||||
//
|
|
||||||
// import "golang.org/x/net/context"
|
|
||||||
//
|
|
||||||
// // User is the type of value stored in the Contexts.
|
|
||||||
// type User struct {...}
|
|
||||||
//
|
|
||||||
// // key is an unexported type for keys defined in this package.
|
|
||||||
// // This prevents collisions with keys defined in other packages.
|
|
||||||
// type key int
|
|
||||||
//
|
|
||||||
// // userKey is the key for user.User values in Contexts. It is
|
|
||||||
// // unexported; clients use user.NewContext and user.FromContext
|
|
||||||
// // instead of using this key directly.
|
|
||||||
// var userKey key = 0
|
|
||||||
//
|
|
||||||
// // NewContext returns a new Context that carries value u.
|
|
||||||
// func NewContext(ctx context.Context, u *User) context.Context {
|
|
||||||
// return context.WithValue(ctx, userKey, u)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // FromContext returns the User value stored in ctx, if any.
|
|
||||||
// func FromContext(ctx context.Context) (*User, bool) {
|
|
||||||
// u, ok := ctx.Value(userKey).(*User)
|
|
||||||
// return u, ok
|
|
||||||
// }
|
|
||||||
Value(key interface{}) interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
// values, and has no deadline. It is typically used by the main function,
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
// initialization, and tests, and as the top-level Context for incoming
|
||||||
|
@ -149,8 +54,3 @@ func Background() Context {
|
||||||
func TODO() Context {
|
func TODO() Context {
|
||||||
return todo
|
return todo
|
||||||
}
|
}
|
||||||
|
|
||||||
// A CancelFunc tells an operation to abandon its work.
|
|
||||||
// A CancelFunc does not wait for the work to stop.
|
|
||||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
|
||||||
type CancelFunc func()
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 go1.9
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import "context" // standard library's context, as of Go 1.7
|
||||||
|
|
||||||
|
// A Context carries a deadline, a cancelation signal, and other values across
|
||||||
|
// API boundaries.
|
||||||
|
//
|
||||||
|
// Context's methods may be called by multiple goroutines simultaneously.
|
||||||
|
type Context = context.Context
|
||||||
|
|
||||||
|
// A CancelFunc tells an operation to abandon its work.
|
||||||
|
// A CancelFunc does not wait for the work to stop.
|
||||||
|
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||||
|
type CancelFunc = context.CancelFunc
|
|
@ -0,0 +1,109 @@
|
||||||
|
// 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 !go1.9
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// A Context carries a deadline, a cancelation signal, and other values across
|
||||||
|
// API boundaries.
|
||||||
|
//
|
||||||
|
// Context's methods may be called by multiple goroutines simultaneously.
|
||||||
|
type Context interface {
|
||||||
|
// Deadline returns the time when work done on behalf of this context
|
||||||
|
// should be canceled. Deadline returns ok==false when no deadline is
|
||||||
|
// set. Successive calls to Deadline return the same results.
|
||||||
|
Deadline() (deadline time.Time, ok bool)
|
||||||
|
|
||||||
|
// Done returns a channel that's closed when work done on behalf of this
|
||||||
|
// context should be canceled. Done may return nil if this context can
|
||||||
|
// never be canceled. Successive calls to Done return the same value.
|
||||||
|
//
|
||||||
|
// WithCancel arranges for Done to be closed when cancel is called;
|
||||||
|
// WithDeadline arranges for Done to be closed when the deadline
|
||||||
|
// expires; WithTimeout arranges for Done to be closed when the timeout
|
||||||
|
// elapses.
|
||||||
|
//
|
||||||
|
// Done is provided for use in select statements:
|
||||||
|
//
|
||||||
|
// // Stream generates values with DoSomething and sends them to out
|
||||||
|
// // until DoSomething returns an error or ctx.Done is closed.
|
||||||
|
// func Stream(ctx context.Context, out chan<- Value) error {
|
||||||
|
// for {
|
||||||
|
// v, err := DoSomething(ctx)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// select {
|
||||||
|
// case <-ctx.Done():
|
||||||
|
// return ctx.Err()
|
||||||
|
// case out <- v:
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// See http://blog.golang.org/pipelines for more examples of how to use
|
||||||
|
// a Done channel for cancelation.
|
||||||
|
Done() <-chan struct{}
|
||||||
|
|
||||||
|
// Err returns a non-nil error value after Done is closed. Err returns
|
||||||
|
// Canceled if the context was canceled or DeadlineExceeded if the
|
||||||
|
// context's deadline passed. No other values for Err are defined.
|
||||||
|
// After Done is closed, successive calls to Err return the same value.
|
||||||
|
Err() error
|
||||||
|
|
||||||
|
// Value returns the value associated with this context for key, or nil
|
||||||
|
// if no value is associated with key. Successive calls to Value with
|
||||||
|
// the same key returns the same result.
|
||||||
|
//
|
||||||
|
// Use context values only for request-scoped data that transits
|
||||||
|
// processes and API boundaries, not for passing optional parameters to
|
||||||
|
// functions.
|
||||||
|
//
|
||||||
|
// A key identifies a specific value in a Context. Functions that wish
|
||||||
|
// to store values in Context typically allocate a key in a global
|
||||||
|
// variable then use that key as the argument to context.WithValue and
|
||||||
|
// Context.Value. A key can be any type that supports equality;
|
||||||
|
// packages should define keys as an unexported type to avoid
|
||||||
|
// collisions.
|
||||||
|
//
|
||||||
|
// Packages that define a Context key should provide type-safe accessors
|
||||||
|
// for the values stores using that key:
|
||||||
|
//
|
||||||
|
// // Package user defines a User type that's stored in Contexts.
|
||||||
|
// package user
|
||||||
|
//
|
||||||
|
// import "golang.org/x/net/context"
|
||||||
|
//
|
||||||
|
// // User is the type of value stored in the Contexts.
|
||||||
|
// type User struct {...}
|
||||||
|
//
|
||||||
|
// // key is an unexported type for keys defined in this package.
|
||||||
|
// // This prevents collisions with keys defined in other packages.
|
||||||
|
// type key int
|
||||||
|
//
|
||||||
|
// // userKey is the key for user.User values in Contexts. It is
|
||||||
|
// // unexported; clients use user.NewContext and user.FromContext
|
||||||
|
// // instead of using this key directly.
|
||||||
|
// var userKey key = 0
|
||||||
|
//
|
||||||
|
// // NewContext returns a new Context that carries value u.
|
||||||
|
// func NewContext(ctx context.Context, u *User) context.Context {
|
||||||
|
// return context.WithValue(ctx, userKey, u)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // FromContext returns the User value stored in ctx, if any.
|
||||||
|
// func FromContext(ctx context.Context) (*User, bool) {
|
||||||
|
// u, ok := ctx.Value(userKey).(*User)
|
||||||
|
// return u, ok
|
||||||
|
// }
|
||||||
|
Value(key interface{}) interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A CancelFunc tells an operation to abandon its work.
|
||||||
|
// A CancelFunc does not wait for the work to stop.
|
||||||
|
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||||
|
type CancelFunc func()
|
|
@ -0,0 +1,51 @@
|
||||||
|
#
|
||||||
|
# This Dockerfile builds a recent curl with HTTP/2 client support, using
|
||||||
|
# a recent nghttp2 build.
|
||||||
|
#
|
||||||
|
# See the Makefile for how to tag it. If Docker and that image is found, the
|
||||||
|
# Go tests use this curl binary for integration tests.
|
||||||
|
#
|
||||||
|
|
||||||
|
FROM ubuntu:trusty
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get upgrade -y && \
|
||||||
|
apt-get install -y git-core build-essential wget
|
||||||
|
|
||||||
|
RUN apt-get install -y --no-install-recommends \
|
||||||
|
autotools-dev libtool pkg-config zlib1g-dev \
|
||||||
|
libcunit1-dev libssl-dev libxml2-dev libevent-dev \
|
||||||
|
automake autoconf
|
||||||
|
|
||||||
|
# The list of packages nghttp2 recommends for h2load:
|
||||||
|
RUN apt-get install -y --no-install-recommends make binutils \
|
||||||
|
autoconf automake autotools-dev \
|
||||||
|
libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
|
||||||
|
libev-dev libevent-dev libjansson-dev libjemalloc-dev \
|
||||||
|
cython python3.4-dev python-setuptools
|
||||||
|
|
||||||
|
# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
|
||||||
|
ENV NGHTTP2_VER 895da9a
|
||||||
|
RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
|
||||||
|
|
||||||
|
WORKDIR /root/nghttp2
|
||||||
|
RUN git reset --hard $NGHTTP2_VER
|
||||||
|
RUN autoreconf -i
|
||||||
|
RUN automake
|
||||||
|
RUN autoconf
|
||||||
|
RUN ./configure
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
|
||||||
|
RUN tar -zxvf curl-7.45.0.tar.gz
|
||||||
|
WORKDIR /root/curl-7.45.0
|
||||||
|
RUN ./configure --with-ssl --with-nghttp2=/usr/local
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
RUN ldconfig
|
||||||
|
|
||||||
|
CMD ["-h"]
|
||||||
|
ENTRYPOINT ["/usr/local/bin/curl"]
|
||||||
|
|
|
@ -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.
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
curlimage:
|
||||||
|
docker build -t gohttp2/curl .
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
This is a work-in-progress HTTP/2 implementation for Go.
|
||||||
|
|
||||||
|
It will eventually live in the Go standard library and won't require
|
||||||
|
any changes to your code to use. It will just be automatic.
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
* The server support is pretty good. A few things are missing
|
||||||
|
but are being worked on.
|
||||||
|
* The client work has just started but shares a lot of code
|
||||||
|
is coming along much quicker.
|
||||||
|
|
||||||
|
Docs are at https://godoc.org/golang.org/x/net/http2
|
||||||
|
|
||||||
|
Demo test server at https://http2.golang.org/
|
||||||
|
|
||||||
|
Help & bug reports welcome!
|
||||||
|
|
||||||
|
Contributing: https://golang.org/doc/contribute.html
|
||||||
|
Bugs: https://golang.org/issue/new?title=x/net/http2:+
|
|
@ -0,0 +1,641 @@
|
||||||
|
// 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 http2
|
||||||
|
|
||||||
|
// A list of the possible cipher suite ids. Taken from
|
||||||
|
// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
|
||||||
|
|
||||||
|
const (
|
||||||
|
cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
|
||||||
|
// Reserved uint16 = 0x001C-1D
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
|
||||||
|
// Reserved uint16 = 0x0047-4F
|
||||||
|
// Reserved uint16 = 0x0050-58
|
||||||
|
// Reserved uint16 = 0x0059-5C
|
||||||
|
// Unassigned uint16 = 0x005D-5F
|
||||||
|
// Reserved uint16 = 0x0060-66
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
|
||||||
|
// Unassigned uint16 = 0x006E-83
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
|
||||||
|
// Unassigned uint16 = 0x00C6-FE
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
|
||||||
|
// Unassigned uint16 = 0x01-55,*
|
||||||
|
cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
|
||||||
|
// Unassigned uint16 = 0x5601 - 0xC000
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
|
||||||
|
cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
|
||||||
|
// Unassigned uint16 = 0xC0B0-FF
|
||||||
|
// Unassigned uint16 = 0xC1-CB,*
|
||||||
|
// Unassigned uint16 = 0xCC00-A7
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
|
||||||
|
cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
|
||||||
|
)
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
// References:
|
||||||
|
// https://tools.ietf.org/html/rfc7540#appendix-A
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case cipher_TLS_NULL_WITH_NULL_NULL,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_DH_anon_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
|
||||||
|
cipher_TLS_KRB5_WITH_DES_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_RC4_128_MD5,
|
||||||
|
cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
|
||||||
|
cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
||||||
|
cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||||
|
cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_RSA_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_RSA_WITH_AES_256_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM,
|
||||||
|
cipher_TLS_PSK_WITH_AES_128_CCM_8,
|
||||||
|
cipher_TLS_PSK_WITH_AES_256_CCM_8:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
// registerHTTPSProtocol calls Transport.RegisterProtocol but
|
||||||
// convering panics into errors.
|
// converting panics into errors.
|
||||||
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
|
|
|
@ -87,13 +87,16 @@ type goAwayFlowError struct{}
|
||||||
|
|
||||||
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
|
||||||
|
|
||||||
// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
|
// connError represents an HTTP/2 ConnectionError error code, along
|
||||||
|
// with a string (for debugging) explaining why.
|
||||||
|
//
|
||||||
// Errors of this type are only returned by the frame parser functions
|
// Errors of this type are only returned by the frame parser functions
|
||||||
// and converted into ConnectionError(ErrCodeProtocol).
|
// and converted into ConnectionError(Code), after stashing away
|
||||||
|
// the Reason into the Framer's errDetail field, accessible via
|
||||||
|
// the (*Framer).ErrorDetail method.
|
||||||
type connError struct {
|
type connError struct {
|
||||||
Code ErrCode
|
Code ErrCode // the ConnectionError error code
|
||||||
Reason string
|
Reason string // additional reason
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e connError) Error() string {
|
func (e connError) Error() string {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -15,29 +14,3 @@ import (
|
||||||
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
return t1.ExpectContinueTimeout
|
return t1.ExpectContinueTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// Reject cipher suites from Appendix A.
|
|
||||||
// "This list includes those cipher suites that do not
|
|
||||||
// offer an ephemeral key exchange and those that are
|
|
||||||
// based on the TLS null, stream or block cipher type"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -52,3 +52,5 @@ func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
|
||||||
func reqBodyIsNoBody(body io.ReadCloser) bool {
|
func reqBodyIsNoBody(body io.ReadCloser) bool {
|
||||||
return body == http.NoBody
|
return body == http.NoBody
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue