mirror of
https://github.com/ManyakRus/crud_generator.git
synced 2025-05-18 10:38:33 +02:00
сделал readme
This commit is contained in:
parent
a21b91ba83
commit
a40b48ea70
58
README.md
58
README.md
@ -1,2 +1,56 @@
|
|||||||
# crud_generator
|
The crud_generator application is designed to automatically generate source code files
|
||||||
CRUD and Model and GRPC source code automatic generator. From Postres SQL database
|
in golang language to perform CRUD operations.
|
||||||
|
|
||||||
|
For each table in the Postgres SQL database, files will be created to perform crud operations:
|
||||||
|
create, read, update, save, delete (or delete + restore)
|
||||||
|
files are generated:
|
||||||
|
1. model - struct structure with all fields from the database, and gorm + db + json annotations
|
||||||
|
2. db - files for performing crud operations, exchange with the database,
|
||||||
|
as well as files with tests
|
||||||
|
3. grpc server - files for performing crud operations over the network, using the GRPC protocol,
|
||||||
|
as well as files with tests
|
||||||
|
4. grpc client - client files for using GRPC by third-party services,
|
||||||
|
as well as files with tests
|
||||||
|
5. nrpc server - files for performing crud operations over the network, using the NRPC protocol (via the NATS message broker),
|
||||||
|
as well as files with tests
|
||||||
|
6. nrpc client - client files for use by NRPC third-party services,
|
||||||
|
as well as files with tests
|
||||||
|
7. crud_starter - a file with functions for switching to the desired protocol db or grpc or nrpc
|
||||||
|
|
||||||
|
Code templates are stored in the bin/templates folder.
|
||||||
|
The code template is a .go file copied from the real project -
|
||||||
|
so it’s easy to make a template (change it to your own) - just copy your file.
|
||||||
|
The code generator replaces part of the code in the template with another code:
|
||||||
|
- name of the database table
|
||||||
|
- model name
|
||||||
|
- adding and removing imports
|
||||||
|
|
||||||
|
Installation procedure:
|
||||||
|
1. Compile this repository
|
||||||
|
make build
|
||||||
|
the crud_generator file will appear in the bin folder
|
||||||
|
|
||||||
|
2. Fill settings in the bin/settings.txt file
|
||||||
|
- connections to your database
|
||||||
|
- name of your new service
|
||||||
|
- URL of your new service
|
||||||
|
- and etc.
|
||||||
|
|
||||||
|
3. Launch crud_generator
|
||||||
|
A new folder with the name of your service will appear in the bin folder,
|
||||||
|
with subfolders and finished files inside.
|
||||||
|
|
||||||
|
4. Copy the finished files to your service.
|
||||||
|
(TODO: later I’ll generate a completely ready-made microservice launched with 1 line of code)
|
||||||
|
|
||||||
|
|
||||||
|
P.S.
|
||||||
|
I generated myself 170,000 lines of code, from 70 tables in the database, for my service.
|
||||||
|
|
||||||
|
|
||||||
|
Source code in Golang language.
|
||||||
|
Tested on Linux Ubuntu
|
||||||
|
Readme from 11/14/2023
|
||||||
|
|
||||||
|
Made by Alexander Nikitin
|
||||||
|
https://github.com/ManyakRus/crud_generator
|
@ -1,27 +1,27 @@
|
|||||||
#---------------------Database settings---------------------
|
#---------------------Database settings---------------------
|
||||||
#DB_HOST - Database server name or ip-address. Only Postgres SQL
|
#DB_HOST - Database server name or ip-address. Only Postgres SQL
|
||||||
DB_HOST=
|
DB_HOST="10.1.9.23"
|
||||||
|
|
||||||
#DB_NAME - Database table name
|
#DB_NAME - Database table name
|
||||||
DB_NAME=
|
DB_NAME="claim"
|
||||||
|
|
||||||
#DB_SCHEME - Database schema name
|
#DB_SCHEME - Database schema name
|
||||||
DB_SCHEME=
|
DB_SCHEME="public"
|
||||||
|
|
||||||
#DB_PORT - Database port number
|
#DB_PORT - Database port number
|
||||||
DB_PORT="5432"
|
DB_PORT="5432"
|
||||||
|
|
||||||
#DB_USER - Database login (user)
|
#DB_USER - Database login (user)
|
||||||
DB_USER=
|
DB_USER="dev"
|
||||||
|
|
||||||
#DB_PASSWORD - Database login password
|
#DB_PASSWORD - Database login password
|
||||||
DB_PASSWORD=
|
DB_PASSWORD="like8Day"
|
||||||
|
|
||||||
#INCLUDE_TABLES - table name filter. Regular expression
|
#INCLUDE_TABLES - table name filter. Regular expression
|
||||||
INCLUDE_TABLES=""
|
INCLUDE_TABLES=""
|
||||||
|
|
||||||
#INCLUDE_TABLES - table name ignore filter. Regular expression
|
#INCLUDE_TABLES - table name ignore filter. Regular expression
|
||||||
EXCLUDE_TABLES=""
|
EXCLUDE_TABLES="ext_"
|
||||||
|
|
||||||
#---------------------Template settings---------------------
|
#---------------------Template settings---------------------
|
||||||
|
|
||||||
@ -97,6 +97,21 @@ NEED_CREATE_MODEL_STRUCT=true
|
|||||||
#NEED_CREATE_MODEL_CRUD - fill "true" if you want create crud operations in model files
|
#NEED_CREATE_MODEL_CRUD - fill "true" if you want create crud operations in model files
|
||||||
NEED_CREATE_MODEL_CRUD=true
|
NEED_CREATE_MODEL_CRUD=true
|
||||||
|
|
||||||
|
#NEED_CREATE_DB_TEST - fill "true" if you want create DB _test.go files
|
||||||
|
NEED_CREATE_DB_TEST=true
|
||||||
|
|
||||||
|
#NEED_CREATE_GRPC_SERVER_TEST - fill "true" if you want create GRPC server _test.go files
|
||||||
|
NEED_CREATE_GRPC_SERVER_TEST=true
|
||||||
|
|
||||||
|
#NEED_CREATE_GRPC_CLIENT_TEST - fill "true" if you want create GRPC client _test.go files
|
||||||
|
NEED_CREATE_GRPC_CLIENT_TEST=true
|
||||||
|
|
||||||
|
#NEED_CREATE_NRPC_SERVER_TEST - fill "true" if you want create NRPC server _test.go files
|
||||||
|
NEED_CREATE_NRPC_SERVER_TEST=true
|
||||||
|
|
||||||
|
#NEED_CREATE_NRPC_CLIENT_TEST - fill "true" if you want create NRPC client _test.go files
|
||||||
|
NEED_CREATE_NRPC_CLIENT_TEST=true
|
||||||
|
|
||||||
#PREFIX_SERVER_GRPC - filename prefix for grpc server files
|
#PREFIX_SERVER_GRPC - filename prefix for grpc server files
|
||||||
PREFIX_SERVER_GRPC="server_grpc_"
|
PREFIX_SERVER_GRPC="server_grpc_"
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StartApp() {
|
func StartApp() {
|
||||||
ConfigMain.LoadEnv()
|
ConfigMain.LoadENV_or_SettingsTXT()
|
||||||
config.FillSettings()
|
config.FillSettings()
|
||||||
config.FillFlags()
|
config.FillFlags()
|
||||||
|
|
||||||
|
51
go.mod
51
go.mod
@ -3,31 +3,44 @@ module github.com/ManyakRus/crud_generator
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ManyakRus/starter v0.0.0-20230913104819-4ee2118a3638
|
github.com/ManyakRus/starter v0.0.0-20231114124845-a0ceb75547b8
|
||||||
github.com/beevik/etree v1.2.0
|
github.com/bxcodec/faker/v3 v3.8.1
|
||||||
|
github.com/davecgh/go-spew v1.1.1
|
||||||
|
github.com/iancoleman/strcase v0.3.0
|
||||||
|
github.com/jimsmart/schema v0.2.1
|
||||||
|
github.com/jinzhu/inflection v1.0.0
|
||||||
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
|
github.com/nats-io/nats.go v1.31.0
|
||||||
|
github.com/ompluscator/dynamic-struct v1.4.0
|
||||||
|
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||||
|
gitlab.aescorp.ru/dsp_dev/claim/sync_service v1.2.24
|
||||||
|
golang.org/x/tools v0.15.0
|
||||||
gorm.io/gorm v1.25.5
|
gorm.io/gorm v1.25.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ManyakRus/logrus v0.0.0-20230913114322-14246ee4c48b // indirect
|
github.com/ManyakRus/logrus v0.0.0-20231019115155-9e6fede0d792 // indirect
|
||||||
github.com/bxcodec/faker/v3 v3.8.1 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
|
||||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
github.com/jackc/pgx/v5 v5.5.0 // indirect
|
||||||
github.com/jimsmart/schema v0.2.1 // indirect
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
github.com/klauspost/compress v1.17.2 // indirect
|
||||||
github.com/ompluscator/dynamic-struct v1.4.0 // indirect
|
github.com/nats-io/nkeys v0.4.6 // indirect
|
||||||
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
gitlab.aescorp.ru/dsp_dev/claim/nikitin v0.0.18 // indirect
|
github.com/nats-rpc/nrpc v0.0.0-20231018091755-18e69326f052 // indirect
|
||||||
golang.org/x/crypto v0.14.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
golang.org/x/mod v0.13.0 // indirect
|
golang.org/x/crypto v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/net v0.18.0 // indirect
|
||||||
golang.org/x/tools v0.14.0 // indirect
|
golang.org/x/sync v0.5.0 // indirect
|
||||||
gorm.io/driver/postgres v1.5.3 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||||
|
google.golang.org/grpc v1.59.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
|
gorm.io/driver/postgres v1.5.4 // indirect
|
||||||
)
|
)
|
||||||
|
546
go.sum
546
go.sum
@ -1,61 +1,183 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||||
github.com/ManyakRus/logrus v0.0.0-20230913114322-14246ee4c48b h1:U17+MOkhFzy9WkjANQhe1JftWq8Opt4gmy2G59wreG8=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/ManyakRus/logrus v0.0.0-20230913114322-14246ee4c48b/go.mod h1:OUyxCVbPW/2lC1e6cM7Am941SJiC88BhNnb24x2R3a8=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/ManyakRus/starter v0.0.0-20230913104819-4ee2118a3638 h1:USOEGx2aGUtq5vJlbr5OhLIRTX252cpv5aYre/QNztg=
|
github.com/ManyakRus/logrus v0.0.0-20231019115155-9e6fede0d792 h1:bxwxD0H3kSUAH3uNk/b74gkImcUiP7dyibmMoVwk338=
|
||||||
github.com/ManyakRus/starter v0.0.0-20230913104819-4ee2118a3638/go.mod h1:wRsJrHV9PcbL8NSxOR14dnWUQ9MSraiZHw1uMQb/ojQ=
|
github.com/ManyakRus/logrus v0.0.0-20231019115155-9e6fede0d792/go.mod h1:OUyxCVbPW/2lC1e6cM7Am941SJiC88BhNnb24x2R3a8=
|
||||||
github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw=
|
github.com/ManyakRus/starter v0.0.0-20231114124845-a0ceb75547b8 h1:Fh5RL2IlfmTA5gZjLyBICNSfVMPmqMUxQ0FTtN/Es/Y=
|
||||||
github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
|
github.com/ManyakRus/starter v0.0.0-20231114124845-a0ceb75547b8/go.mod h1:a+wYuguDadLR6xaj9fN8m6acWhUjzPuxaPtZfJhMNW4=
|
||||||
|
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bxcodec/faker/v3 v3.8.1 h1:qO/Xq19V6uHt2xujwpaetgKhraGCapqY2CRWGD/SqcM=
|
github.com/bxcodec/faker/v3 v3.8.1 h1:qO/Xq19V6uHt2xujwpaetgKhraGCapqY2CRWGD/SqcM=
|
||||||
github.com/bxcodec/faker/v3 v3.8.1/go.mod h1:DdSDccxF5msjFo5aO4vrobRQ8nIApg8kq3QWPEQD6+o=
|
github.com/bxcodec/faker/v3 v3.8.1/go.mod h1:DdSDccxF5msjFo5aO4vrobRQ8nIApg8kq3QWPEQD6+o=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
|
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
|
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
|
github.com/godror/godror v0.36.0 h1:4kymETiaTOJcyF5+47JSUs44Pi0R9bTwsWtBTWqAVRs=
|
||||||
github.com/godror/godror v0.36.0/go.mod h1:jW1+pN+z/V0h28p9XZXVNtEvfZP/2EBfaSjKJLp3E4g=
|
github.com/godror/godror v0.36.0/go.mod h1:jW1+pN+z/V0h28p9XZXVNtEvfZP/2EBfaSjKJLp3E4g=
|
||||||
|
github.com/godror/knownpb v0.1.0 h1:dJPK8s/I3PQzGGaGcUStL2zIaaICNzKKAK8BzP1uLio=
|
||||||
github.com/godror/knownpb v0.1.0/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE=
|
github.com/godror/knownpb v0.1.0/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
|
github.com/jackc/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw=
|
||||||
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/jimsmart/schema v0.2.1 h1:MsSsqq0i86bUskhJJZ6RnrgscbDeBMalLZym6Hx9l3U=
|
github.com/jimsmart/schema v0.2.1 h1:MsSsqq0i86bUskhJJZ6RnrgscbDeBMalLZym6Hx9l3U=
|
||||||
github.com/jimsmart/schema v0.2.1/go.mod h1:4O5InKFd6Fv1xsegHVRLW/Zzm6U2iOqfE8PaI/f+wMU=
|
github.com/jimsmart/schema v0.2.1/go.mod h1:4O5InKFd6Fv1xsegHVRLW/Zzm6U2iOqfE8PaI/f+wMU=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
@ -64,12 +186,62 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
|||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
|
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||||
|
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
|
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
||||||
|
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
|
||||||
|
github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
|
||||||
|
github.com/nats-io/nats-server/v2 v2.9.9 h1:bmj0RhvHOc8+z5/RuhI38GqPwtkFAHQuU3e99FVA/TI=
|
||||||
|
github.com/nats-io/nats-server/v2 v2.9.9/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
|
||||||
|
github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
|
||||||
|
github.com/nats-io/nats.go v1.25.0/go.mod h1:D2WALIhz7V8M0pH8Scx8JZXlg6Oqz5VG+nQkK8nJdvg=
|
||||||
|
github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E=
|
||||||
|
github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8=
|
||||||
|
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||||
|
github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
|
||||||
|
github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY=
|
||||||
|
github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts=
|
||||||
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
github.com/nats-rpc/nrpc v0.0.0-20231018091755-18e69326f052 h1:HT5YZLs3V3KMF4LzR7PbKhR1SgxS+FXKyOcPs7rBcNg=
|
||||||
|
github.com/nats-rpc/nrpc v0.0.0-20231018091755-18e69326f052/go.mod h1:dQ6Gva1zNUdl6n9C9P7jPRfI0TB83/5N5uuJ7MMWT0E=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68=
|
github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68=
|
||||||
github.com/ompluscator/dynamic-struct v1.4.0 h1:I/Si9LZtItSwiTMe7vosEuIu2TKdOvWbE3R/lokpN4Q=
|
github.com/ompluscator/dynamic-struct v1.4.0 h1:I/Si9LZtItSwiTMe7vosEuIu2TKdOvWbE3R/lokpN4Q=
|
||||||
@ -77,6 +249,7 @@ github.com/ompluscator/dynamic-struct v1.4.0/go.mod h1:ADQ1+6Ox1D+ntuNwTHyl1NvpA
|
|||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||||
@ -94,53 +267,170 @@ github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8lu
|
|||||||
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||||
|
github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
|
||||||
github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
|
github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
|
||||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
|
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
|
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||||
|
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
|
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e h1:zWKUYT07mGmVBH+9UgnHXd/ekCK99C8EbDSAt5qsjXE=
|
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e h1:zWKUYT07mGmVBH+9UgnHXd/ekCK99C8EbDSAt5qsjXE=
|
||||||
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||||
|
github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4=
|
||||||
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
gitlab.aescorp.ru/dsp_dev/claim/nikitin v0.0.18 h1:nXBjZn3uhgf2E+J9HdxT/I2w3/P+HRvdOb5MkcrxT14=
|
gitlab.aescorp.ru/dsp_dev/claim/sync_service v1.2.24 h1:sUIyfhb7Yq3hVeqFu0ti1zVhk5NDuGgoIbYXFecBhFU=
|
||||||
gitlab.aescorp.ru/dsp_dev/claim/nikitin v0.0.18/go.mod h1:JhYqHYfOCPWwbCIJwZDJ8V+Hoq/9ErxBg9bypjwblmE=
|
gitlab.aescorp.ru/dsp_dev/claim/sync_service v1.2.24/go.mod h1:WDjha5KBoluGomO6iq41ZDiEaEFj1KPHtOSf9+usk/s=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
@ -149,86 +439,275 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
|||||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
|
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||||
|
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||||
|
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
|
||||||
|
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||||
|
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
@ -236,11 +715,18 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
|
gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo=
|
||||||
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
|
gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0=
|
||||||
gorm.io/driver/postgres v1.5.3 h1:qKGY5CPHOuj47K/VxbCXJfFvIUeqMSXXadqdCY+MbBU=
|
|
||||||
gorm.io/driver/postgres v1.5.3/go.mod h1:F+LtvlFhZT7UBiA81mC9W6Su3D4WUhSboc/36QZU0gk=
|
|
||||||
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
|
|
||||||
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
||||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
@ -25,11 +25,16 @@ type SettingsINI struct {
|
|||||||
TEMPLATE_SERVICE_NAME string
|
TEMPLATE_SERVICE_NAME string
|
||||||
TEMPLATE_FOLDERNAME_CRUD_STARTER string
|
TEMPLATE_FOLDERNAME_CRUD_STARTER string
|
||||||
TEMPLATE_FOLDERNAME_ALIAS string
|
TEMPLATE_FOLDERNAME_ALIAS string
|
||||||
NEED_CREATE_CRUD bool
|
|
||||||
NEED_CREATE_GRPC bool
|
|
||||||
NEED_CREATE_NRPC bool
|
|
||||||
NEED_CREATE_MODEL_STRUCT bool
|
NEED_CREATE_MODEL_STRUCT bool
|
||||||
NEED_CREATE_MODEL_CRUD bool
|
NEED_CREATE_MODEL_CRUD bool
|
||||||
|
NEED_CREATE_DB bool
|
||||||
|
NEED_CREATE_DB_TEST bool
|
||||||
|
NEED_CREATE_GRPC bool
|
||||||
|
NEED_CREATE_GRPC_SERVER_TEST bool
|
||||||
|
NEED_CREATE_GRPC_CLIENT_TEST bool
|
||||||
|
NEED_CREATE_NRPC bool
|
||||||
|
NEED_CREATE_NRPC_SERVER_TEST bool
|
||||||
|
NEED_CREATE_NRPC_CLIENT_TEST bool
|
||||||
SERVICE_NAME string
|
SERVICE_NAME string
|
||||||
SERVICE_REPOSITORY_URL string
|
SERVICE_REPOSITORY_URL string
|
||||||
TEXT_TEMPLATE_MODEL string
|
TEXT_TEMPLATE_MODEL string
|
||||||
@ -42,11 +47,6 @@ type SettingsINI struct {
|
|||||||
PREFIX_SERVER_GRPC string
|
PREFIX_SERVER_GRPC string
|
||||||
COMMENT_MODEL_STRUCT string
|
COMMENT_MODEL_STRUCT string
|
||||||
TEXT_MODULE_GENERATED string
|
TEXT_MODULE_GENERATED string
|
||||||
NEED_CREATE_DB_TEST bool
|
|
||||||
NEED_CREATE_GRPC_SERVER_TEST bool
|
|
||||||
NEED_CREATE_GRPC_CLIENT_TEST bool
|
|
||||||
NEED_CREATE_NRPC_SERVER_TEST bool
|
|
||||||
NEED_CREATE_NRPC_CLIENT_TEST bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FillSettings загружает переменные окружения в структуру из переменных окружения
|
// FillSettings загружает переменные окружения в структуру из переменных окружения
|
||||||
@ -75,8 +75,8 @@ func FillSettings() {
|
|||||||
|
|
||||||
sHAS_IS_DELETED := os.Getenv("HAS_IS_DELETED")
|
sHAS_IS_DELETED := os.Getenv("HAS_IS_DELETED")
|
||||||
|
|
||||||
sNEED_CRUD := os.Getenv("NEED_CREATE_CRUD")
|
sNEED_CREATE_DB := os.Getenv("NEED_CREATE_DB")
|
||||||
Settings.NEED_CREATE_CRUD = BoolFromString(sNEED_CRUD)
|
Settings.NEED_CREATE_DB = BoolFromString(sNEED_CREATE_DB)
|
||||||
|
|
||||||
sNEED_GRPC := os.Getenv("NEED_CREATE_GRPC")
|
sNEED_GRPC := os.Getenv("NEED_CREATE_GRPC")
|
||||||
Settings.NEED_CREATE_GRPC = BoolFromString(sNEED_GRPC)
|
Settings.NEED_CREATE_GRPC = BoolFromString(sNEED_GRPC)
|
||||||
|
@ -29,7 +29,7 @@ func CreateAllFiles(MapAll map[string]*types.Table) error {
|
|||||||
func CreateFileCrudStarter(MapAll map[string]*types.Table) error {
|
func CreateFileCrudStarter(MapAll map[string]*types.Table) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if config.Settings.NEED_CREATE_CRUD == false {
|
if config.Settings.NEED_CREATE_DB == false {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,13 @@ func CreateAllFiles(MapAll map[string]*types.Table) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//файлы db
|
//файлы db
|
||||||
|
if config.Settings.NEED_CREATE_DB_TEST == true {
|
||||||
err = CreateFiles(Table1)
|
err = CreateFiles(Table1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("CreateFiles() table: ", Table1.Name, " error: ", err)
|
log.Error("CreateFiles() table: ", Table1.Name, " error: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//тестовые файлы db
|
//тестовые файлы db
|
||||||
if config.Settings.NEED_CREATE_DB_TEST == true {
|
if config.Settings.NEED_CREATE_DB_TEST == true {
|
||||||
err = CreateTestFiles(Table1)
|
err = CreateTestFiles(Table1)
|
||||||
|
@ -93,7 +93,7 @@ func CreateAllFolders() {
|
|||||||
log.Info("CreateFolder() ", Filename)
|
log.Info("CreateFolder() ", Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Settings.NEED_CREATE_CRUD == true {
|
if config.Settings.NEED_CREATE_DB == true {
|
||||||
//db
|
//db
|
||||||
Filename = dir + config.Settings.SERVICE_NAME + micro.SeparatorFile() + config.Settings.TEMPLATE_FOLDERNAME_DB
|
Filename = dir + config.Settings.SERVICE_NAME + micro.SeparatorFile() + config.Settings.TEMPLATE_FOLDERNAME_DB
|
||||||
ok, err = micro.FileExists(Filename)
|
ok, err = micro.FileExists(Filename)
|
||||||
|
@ -98,7 +98,9 @@ func RenameReservedName(s string) string {
|
|||||||
// FmtFieldName formats a string as a struct key
|
// FmtFieldName formats a string as a struct key
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
|
//
|
||||||
// fmtFieldName("foo_id")
|
// fmtFieldName("foo_id")
|
||||||
|
//
|
||||||
// Output: FooID
|
// Output: FooID
|
||||||
func FmtFieldName(s string) string {
|
func FmtFieldName(s string) string {
|
||||||
name := lintFieldName(s)
|
name := lintFieldName(s)
|
||||||
|
57
readme.rus
Normal file
57
readme.rus
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
Приложение crud_generator предназначено для автоматической генерации файлов исходного кода
|
||||||
|
на языке golang для выполнения операций CRUD.
|
||||||
|
|
||||||
|
Для каждой таблицы в базе данных Postgres SQL будут сделаны файлы для выполнения crud операций:
|
||||||
|
create, read, update, save, delete (или delete + restore)
|
||||||
|
генерируются файлы:
|
||||||
|
1. model - структура struct со всеми полями из БД, и аннотациями gorm + db + json
|
||||||
|
2. db - файлы выполнения crud операций, обмен с базой данных,
|
||||||
|
а также файлы с тестами
|
||||||
|
3. grpc server - файлы для выполнения crud операций по сети, по протоколу GRPC,
|
||||||
|
а также файлы с тестами
|
||||||
|
4. grpc client - файлы клиенты для использования GRPC сторонними сервисами,
|
||||||
|
а также файлы с тестами
|
||||||
|
5. nrpc server - файлы для выполнения crud операций по сети, по протоколу NRPC (через брокер сообщений NATS),
|
||||||
|
а также файлы с тестами
|
||||||
|
6. nrpc client - файлы клиенты для использования NRPC сторонними сервисами,
|
||||||
|
а также файлы с тестами
|
||||||
|
7. crud_starter - файл с функциями переключения на нужный протокол db или grpc или nrpc
|
||||||
|
|
||||||
|
Шаблоны кода хранятся в папке bin/templates.
|
||||||
|
Шаблон кода - это файл .go скопированный из реального проекта -
|
||||||
|
поэтому шаблон сделать (поменять на свой) легко - просто скопировать свой файл.
|
||||||
|
Кодогенератор выполняет замену части кода в шаблоне на другой код:
|
||||||
|
- название таблицы БД
|
||||||
|
- название модели
|
||||||
|
- добавление и убирание импортов
|
||||||
|
|
||||||
|
Порядок установки:
|
||||||
|
1. Скомпилировать этот репозиторий
|
||||||
|
make build
|
||||||
|
в папке bin появится файл crud_generator
|
||||||
|
|
||||||
|
2. Заполнить найстройки в файле bin/settings.txt
|
||||||
|
- подключения к вашей базе данных
|
||||||
|
- имя вашего нового сервиса
|
||||||
|
- URL вашего нового сервиса
|
||||||
|
- и др.
|
||||||
|
|
||||||
|
3. Запустить crud_generator
|
||||||
|
В папке bin появится новая папка с именем вашего сервиса,
|
||||||
|
с подпапками и готовыми файлами внутри.
|
||||||
|
|
||||||
|
4. Скопировать готовые файлы в свой сервис.
|
||||||
|
(TODO: попозже сделаю генерацию полностью готового микросервиса, запускаемого 1 строчкой кода)
|
||||||
|
|
||||||
|
|
||||||
|
P.S.
|
||||||
|
Я сгенерировал себе 170000 строк кода, из 70 таблиц в базе данных, для своего сервиса.
|
||||||
|
|
||||||
|
|
||||||
|
Исходный код на языке Golang.
|
||||||
|
Тестировал на Linux Ubuntu
|
||||||
|
Реадми от 14.11.2023
|
||||||
|
|
||||||
|
Сделал Александр Никитин
|
||||||
|
https://github.com/ManyakRus/crud_generator
|
||||||
|
|
2
vendor/github.com/ManyakRus/logrus/.travis.yml
generated
vendored
2
vendor/github.com/ManyakRus/logrus/.travis.yml
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
language: go
|
language: go
|
||||||
go_import_path: github.com/sirupsen/logrus
|
go_import_path: github.com/ManyakRus/logrus
|
||||||
git:
|
git:
|
||||||
depth: 1
|
depth: 1
|
||||||
env:
|
env:
|
||||||
|
6
vendor/github.com/ManyakRus/logrus/Makefile
generated
vendored
Normal file
6
vendor/github.com/ManyakRus/logrus/Makefile
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SERVICEURL=github.com/sirupsen/logrus
|
||||||
|
|
||||||
|
NEW_REPO=github.com/ManyakRus/logrus
|
||||||
|
|
||||||
|
newrepo:
|
||||||
|
find -name *.go -not -path "*/vendor/*"|xargs sed -i 's+$(SERVICEURL)+$(NEW_REPO)+g'
|
36
vendor/github.com/ManyakRus/logrus/README.md
generated
vendored
36
vendor/github.com/ManyakRus/logrus/README.md
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://github.com/sirupsen/logrus/actions?query=workflow%3ACI) [](https://travis-ci.org/sirupsen/logrus) [](https://pkg.go.dev/github.com/sirupsen/logrus)
|
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://github.com/ManyakRus/logrus/actions?query=workflow%3ACI) [](https://travis-ci.org/sirupsen/logrus) [](https://pkg.go.dev/github.com/ManyakRus/logrus)
|
||||||
|
|
||||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
Logrus is a structured logger for Go (golang), completely API compatible with
|
||||||
the standard library logger.
|
the standard library logger.
|
||||||
@ -28,12 +28,12 @@ import Logrus as both upper- and lower-case. Due to the Go package environment,
|
|||||||
this caused issues in the community and we needed a standard. Some environments
|
this caused issues in the community and we needed a standard. Some environments
|
||||||
experienced problems with the upper-case variant, so the lower-case was decided.
|
experienced problems with the upper-case variant, so the lower-case was decided.
|
||||||
Everything using `logrus` will need to use the lower-case:
|
Everything using `logrus` will need to use the lower-case:
|
||||||
`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
|
`github.com/ManyakRus/logrus`. Any package that isn't, should be changed.
|
||||||
|
|
||||||
To fix Glide, see [these
|
To fix Glide, see [these
|
||||||
comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
|
comments](https://github.com/ManyakRus/logrus/issues/553#issuecomment-306591437).
|
||||||
For an in-depth explanation of the casing issue, see [this
|
For an in-depth explanation of the casing issue, see [this
|
||||||
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
|
comment](https://github.com/ManyakRus/logrus/issues/570#issuecomment-313933276).
|
||||||
|
|
||||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
Nicely color-coded in development (when a TTY is attached, otherwise just
|
||||||
plain text):
|
plain text):
|
||||||
@ -43,7 +43,7 @@ plain text):
|
|||||||
With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
|
With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
|
||||||
or Splunk:
|
or Splunk:
|
||||||
|
|
||||||
```json
|
```text
|
||||||
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
|
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
|
||||||
ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
|
ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ go test -bench=.*CallerTracing
|
|||||||
|
|
||||||
The organization's name was changed to lower-case--and this will not be changed
|
The organization's name was changed to lower-case--and this will not be changed
|
||||||
back. If you are getting import conflicts due to case sensitivity, please use
|
back. If you are getting import conflicts due to case sensitivity, please use
|
||||||
the lower-case import: `github.com/sirupsen/logrus`.
|
the lower-case import: `github.com/ManyakRus/logrus`.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ The simplest way to use Logrus is simply the package-level exported logger:
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/ManyakRus/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -130,7 +130,7 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Note that it's completely api-compatible with the stdlib logger, so you can
|
Note that it's completely api-compatible with the stdlib logger, so you can
|
||||||
replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"`
|
replace your `log` imports everywhere with `log "github.com/ManyakRus/logrus"`
|
||||||
and you'll now have the flexibility of Logrus. You can customize it all you
|
and you'll now have the flexibility of Logrus. You can customize it all you
|
||||||
want:
|
want:
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/ManyakRus/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -190,7 +190,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/ManyakRus/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a new instance of the logger. You can have any number of instances.
|
// Create a new instance of the logger. You can have any number of instances.
|
||||||
@ -265,9 +265,9 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/ManyakRus/logrus"
|
||||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
|
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
|
||||||
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
logrus_syslog "github.com/ManyakRus/logrus/hooks/syslog"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ func init() {
|
|||||||
```
|
```
|
||||||
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
||||||
|
|
||||||
A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
|
A list of currently known service hooks can be found in this wiki [page](https://github.com/ManyakRus/logrus/wiki/Hooks)
|
||||||
|
|
||||||
|
|
||||||
#### Level logging
|
#### Level logging
|
||||||
@ -340,7 +340,7 @@ could do:
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/ManyakRus/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -372,9 +372,9 @@ The built-in logging formatters are:
|
|||||||
* When colors are enabled, levels are truncated to 4 characters by default. To disable
|
* When colors are enabled, levels are truncated to 4 characters by default. To disable
|
||||||
truncation set the `DisableLevelTruncation` field to `true`.
|
truncation set the `DisableLevelTruncation` field to `true`.
|
||||||
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
|
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
|
||||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
|
* All options are listed in the [generated docs](https://godoc.org/github.com/ManyakRus/logrus#TextFormatter).
|
||||||
* `logrus.JSONFormatter`. Logs fields as JSON.
|
* `logrus.JSONFormatter`. Logs fields as JSON.
|
||||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
|
* All options are listed in the [generated docs](https://godoc.org/github.com/ManyakRus/logrus#JSONFormatter).
|
||||||
|
|
||||||
Third party logging formatters:
|
Third party logging formatters:
|
||||||
|
|
||||||
@ -462,8 +462,8 @@ Logrus has a built in facility for asserting the presence of log messages. This
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import(
|
import(
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/ManyakRus/logrus"
|
||||||
"github.com/sirupsen/logrus/hooks/test"
|
"github.com/ManyakRus/logrus/hooks/test"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
6
vendor/github.com/ManyakRus/logrus/doc.go
generated
vendored
6
vendor/github.com/ManyakRus/logrus/doc.go
generated
vendored
@ -1,13 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
|
Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
|
||||||
|
|
||||||
|
|
||||||
The simplest way to use Logrus is simply the package-level exported logger:
|
The simplest way to use Logrus is simply the package-level exported logger:
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/ManyakRus/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -19,8 +18,9 @@ The simplest way to use Logrus is simply the package-level exported logger:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
|
|
||||||
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
|
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
|
||||||
|
|
||||||
For a full guide visit https://github.com/sirupsen/logrus
|
For a full guide visit https://github.com/ManyakRus/logrus
|
||||||
*/
|
*/
|
||||||
package logrus
|
package logrus
|
||||||
|
2
vendor/github.com/ManyakRus/logrus/entry.go
generated
vendored
2
vendor/github.com/ManyakRus/logrus/entry.go
generated
vendored
@ -257,7 +257,7 @@ func (entry *Entry) log(level Level, msg string) {
|
|||||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
||||||
// directly here.
|
// directly here.
|
||||||
if level <= PanicLevel {
|
if level <= PanicLevel {
|
||||||
panic(entry) //sanek
|
//panic(entry) //sanek не было
|
||||||
panic(newEntry)
|
panic(newEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/ManyakRus/logrus/json_formatter.go
generated
vendored
2
vendor/github.com/ManyakRus/logrus/json_formatter.go
generated
vendored
@ -66,7 +66,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case error:
|
case error:
|
||||||
// Otherwise errors are ignored by `encoding/json`
|
// Otherwise errors are ignored by `encoding/json`
|
||||||
// https://github.com/sirupsen/logrus/issues/137
|
// https://github.com/ManyakRus/logrus/issues/137
|
||||||
data[k] = v.Error()
|
data[k] = v.Error()
|
||||||
default:
|
default:
|
||||||
data[k] = v
|
data[k] = v
|
||||||
|
2
vendor/github.com/ManyakRus/logrus/terminal_check_bsd.go
generated
vendored
2
vendor/github.com/ManyakRus/logrus/terminal_check_bsd.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build darwin dragonfly freebsd netbsd openbsd
|
// +build darwin dragonfly freebsd netbsd openbsd hurd
|
||||||
// +build !js
|
// +build !js
|
||||||
|
|
||||||
package logrus
|
package logrus
|
||||||
|
2
vendor/github.com/ManyakRus/logrus/terminal_check_unix.go
generated
vendored
2
vendor/github.com/ManyakRus/logrus/terminal_check_unix.go
generated
vendored
@ -1,5 +1,7 @@
|
|||||||
|
//go:build (linux || aix || zos) && !js && !wasi
|
||||||
// +build linux aix zos
|
// +build linux aix zos
|
||||||
// +build !js
|
// +build !js
|
||||||
|
// +build !wasi
|
||||||
|
|
||||||
package logrus
|
package logrus
|
||||||
|
|
||||||
|
8
vendor/github.com/ManyakRus/logrus/terminal_check_wasi.go
generated
vendored
Normal file
8
vendor/github.com/ManyakRus/logrus/terminal_check_wasi.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build wasi
|
||||||
|
// +build wasi
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
func isTerminal(fd int) bool {
|
||||||
|
return false
|
||||||
|
}
|
8
vendor/github.com/ManyakRus/logrus/terminal_check_wasip1.go
generated
vendored
Normal file
8
vendor/github.com/ManyakRus/logrus/terminal_check_wasip1.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//go:build wasip1
|
||||||
|
// +build wasip1
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
func isTerminal(fd int) bool {
|
||||||
|
return false
|
||||||
|
}
|
36
vendor/github.com/ManyakRus/logrus/writer.go
generated
vendored
36
vendor/github.com/ManyakRus/logrus/writer.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer at INFO level. See WriterLevel for details.
|
// Writer at INFO level. See WriterLevel for details.
|
||||||
@ -20,15 +21,18 @@ func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
|||||||
return NewEntry(logger).WriterLevel(level)
|
return NewEntry(logger).WriterLevel(level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writer returns an io.Writer that writes to the logger at the info log level
|
||||||
func (entry *Entry) Writer() *io.PipeWriter {
|
func (entry *Entry) Writer() *io.PipeWriter {
|
||||||
return entry.WriterLevel(InfoLevel)
|
return entry.WriterLevel(InfoLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriterLevel returns an io.Writer that writes to the logger at the given log level
|
||||||
func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
|
func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
|
|
||||||
var printFunc func(args ...interface{})
|
var printFunc func(args ...interface{})
|
||||||
|
|
||||||
|
// Determine which log function to use based on the specified log level
|
||||||
switch level {
|
switch level {
|
||||||
case TraceLevel:
|
case TraceLevel:
|
||||||
printFunc = entry.Trace
|
printFunc = entry.Trace
|
||||||
@ -48,23 +52,51 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
|
|||||||
printFunc = entry.Print
|
printFunc = entry.Print
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start a new goroutine to scan the input and write it to the logger using the specified print function.
|
||||||
|
// It splits the input into chunks of up to 64KB to avoid buffer overflows.
|
||||||
go entry.writerScanner(reader, printFunc)
|
go entry.writerScanner(reader, printFunc)
|
||||||
|
|
||||||
|
// Set a finalizer function to close the writer when it is garbage collected
|
||||||
runtime.SetFinalizer(writer, writerFinalizer)
|
runtime.SetFinalizer(writer, writerFinalizer)
|
||||||
|
|
||||||
return writer
|
return writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writerScanner scans the input from the reader and writes it to the logger
|
||||||
func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
|
func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
for scanner.Scan() {
|
|
||||||
printFunc(scanner.Text())
|
// Set the buffer size to the maximum token size to avoid buffer overflows
|
||||||
|
scanner.Buffer(make([]byte, bufio.MaxScanTokenSize), bufio.MaxScanTokenSize)
|
||||||
|
|
||||||
|
// Define a split function to split the input into chunks of up to 64KB
|
||||||
|
chunkSize := bufio.MaxScanTokenSize // 64KB
|
||||||
|
splitFunc := func(data []byte, atEOF bool) (int, []byte, error) {
|
||||||
|
if len(data) >= chunkSize {
|
||||||
|
return chunkSize, data[:chunkSize], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bufio.ScanLines(data, atEOF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the custom split function to split the input
|
||||||
|
scanner.Split(splitFunc)
|
||||||
|
|
||||||
|
// Scan the input and write it to the logger using the specified print function
|
||||||
|
for scanner.Scan() {
|
||||||
|
printFunc(strings.TrimRight(scanner.Text(), "\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there was an error while scanning the input, log an error
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
entry.Errorf("Error while reading from Writer: %s", err)
|
entry.Errorf("Error while reading from Writer: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the reader when we are done
|
||||||
reader.Close()
|
reader.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriterFinalizer is a finalizer function that closes then given writer when it is garbage collected
|
||||||
func writerFinalizer(writer *io.PipeWriter) {
|
func writerFinalizer(writer *io.PipeWriter) {
|
||||||
writer.Close()
|
writer.Close()
|
||||||
}
|
}
|
||||||
|
68
vendor/github.com/ManyakRus/starter/config/config.go
generated
vendored
68
vendor/github.com/ManyakRus/starter/config/config.go
generated
vendored
@ -3,9 +3,9 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/joho/godotenv"
|
|
||||||
"github.com/ManyakRus/starter/logger"
|
"github.com/ManyakRus/starter/logger"
|
||||||
"github.com/ManyakRus/starter/micro"
|
"github.com/ManyakRus/starter/micro"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
//log "github.com/sirupsen/logrus"
|
//log "github.com/sirupsen/logrus"
|
||||||
//log "github.com/sirupsen/logrus"
|
//log "github.com/sirupsen/logrus"
|
||||||
//"gitlab.aescorp.ru/dsp_dev/notifier/notifier_adp_eml/internal/v0/app/types"
|
//"gitlab.aescorp.ru/dsp_dev/notifier/notifier_adp_eml/internal/v0/app/types"
|
||||||
@ -15,7 +15,7 @@ import (
|
|||||||
// log хранит используемый логгер
|
// log хранит используемый логгер
|
||||||
var log = logger.GetLog()
|
var log = logger.GetLog()
|
||||||
|
|
||||||
// LoadEnv - загружает переменные окружения в структуру из файла или из переменных окружения
|
// LoadEnv - загружает из файла .env переменные в переменные окружения
|
||||||
func LoadEnv() {
|
func LoadEnv() {
|
||||||
|
|
||||||
dir := micro.ProgramDir()
|
dir := micro.ProgramDir()
|
||||||
@ -23,20 +23,66 @@ func LoadEnv() {
|
|||||||
LoadEnv_from_file(filename)
|
LoadEnv_from_file(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadEnv_from_file загружает переменные окружения в структуру из файла или из переменных окружения
|
// LoadEnv - загружает из файла .env переменные в переменные окружения, возвращает ошибку
|
||||||
|
func LoadEnv_err() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
dir := micro.ProgramDir()
|
||||||
|
filename := dir + ".env"
|
||||||
|
err = LoadEnv_from_file_err(filename)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSettingsTxt - загружает из файла settings.txt переменные в переменные окружения
|
||||||
|
func LoadSettingsTxt() {
|
||||||
|
|
||||||
|
dir := micro.ProgramDir()
|
||||||
|
filename := dir + "settings.txt"
|
||||||
|
LoadEnv_from_file(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSettingsTxt_err - загружает из файла settings.txt переменные в переменные окружения, возвращает ошибку
|
||||||
|
func LoadSettingsTxt_err() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
dir := micro.ProgramDir()
|
||||||
|
filename := dir + "settings.txt"
|
||||||
|
err = LoadEnv_from_file_err(filename)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadEnv_from_file загружает из файла переменные в переменные окружения
|
||||||
func LoadEnv_from_file(filename string) {
|
func LoadEnv_from_file(filename string) {
|
||||||
|
|
||||||
err := godotenv.Load(filename)
|
FilenameShort := micro.LastWord(filename)
|
||||||
|
|
||||||
|
err := LoadEnv_from_file_err(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Can not parse .env file: ", filename, " warning: "+err.Error())
|
log.Debug("Can not parse "+FilenameShort+" file: ", filename, " warning: "+err.Error())
|
||||||
} else {
|
} else {
|
||||||
log.Info("load .env from file: ", filename)
|
log.Info("load "+FilenameShort+" from file: ", filename)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOG_LEVEL := os.Getenv("LOG_LEVEL")
|
// LoadEnv_from_file загружает из файла переменные в переменные окружения, возвращает ошибку
|
||||||
//if LOG_LEVEL == "" {
|
func LoadEnv_from_file_err(filename string) error {
|
||||||
// LOG_LEVEL = "info"
|
var err error
|
||||||
//}
|
|
||||||
//logger.SetLevel(LOG_LEVEL)
|
|
||||||
|
|
||||||
|
err = godotenv.Load(filename)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadENV_or_SettingsTXT - загружает из файла .env или settings.txt переменные в переменные окружения
|
||||||
|
func LoadENV_or_SettingsTXT() {
|
||||||
|
errENV := LoadEnv_err()
|
||||||
|
var err2 error
|
||||||
|
if errENV != nil {
|
||||||
|
err2 = LoadSettingsTxt_err()
|
||||||
|
}
|
||||||
|
if err2 != nil {
|
||||||
|
log.Panic("LoadENV_or_SettingsTXT() error: ", err2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
60
vendor/github.com/ManyakRus/starter/micro/microfunctions.go
generated
vendored
60
vendor/github.com/ManyakRus/starter/micro/microfunctions.go
generated
vendored
@ -676,6 +676,21 @@ func BoolFromInt(i int) bool {
|
|||||||
return Otvet
|
return Otvet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoolFromString - возвращает true если строка = true, или =1
|
||||||
|
func BoolFromString(s string) bool {
|
||||||
|
Otvet := false
|
||||||
|
|
||||||
|
s = strings.TrimLeft(s, " ")
|
||||||
|
s = strings.TrimRight(s, " ")
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
|
||||||
|
if s == "true" || s == "1" {
|
||||||
|
Otvet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return Otvet
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteFileSeperator - убирает в конце / или \
|
// DeleteFileSeperator - убирает в конце / или \
|
||||||
func DeleteFileSeperator(dir string) string {
|
func DeleteFileSeperator(dir string) string {
|
||||||
Otvet := dir
|
Otvet := dir
|
||||||
@ -692,3 +707,48 @@ func DeleteFileSeperator(dir string) string {
|
|||||||
|
|
||||||
return Otvet
|
return Otvet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateFolder - создаёт папку на диске
|
||||||
|
func CreateFolder(FilenameFull string, FilePermissions uint32) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
FileMode1 := os.FileMode(FilePermissions)
|
||||||
|
if FilePermissions == 0 {
|
||||||
|
FileMode1 = os.FileMode(0700)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(FilenameFull); errors.Is(err, os.ErrNotExist) {
|
||||||
|
err := os.Mkdir(FilenameFull, FileMode1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFolder - создаёт папку на диске
|
||||||
|
func DeleteFolder(FilenameFull string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if _, err := os.Stat(FilenameFull); errors.Is(err, os.ErrNotExist) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.RemoveAll(FilenameFull)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextDone - возвращает true если контекст завершен
|
||||||
|
func ContextDone(ctx context.Context) bool {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
vendor/github.com/ManyakRus/starter/postgres_gorm/postgres_gorm.go
generated
vendored
3
vendor/github.com/ManyakRus/starter/postgres_gorm/postgres_gorm.go
generated
vendored
@ -225,7 +225,7 @@ func WaitStop() {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-contextmain.GetContext().Done():
|
case <-contextmain.GetContext().Done():
|
||||||
log.Warn("Context app is canceled.")
|
log.Warn("Context app is canceled. Postgres gorm.")
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -321,6 +321,7 @@ func GetConnection() *gorm.DB {
|
|||||||
func ping_go() {
|
func ping_go() {
|
||||||
|
|
||||||
ticker := time.NewTicker(60 * time.Second)
|
ticker := time.NewTicker(60 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
addr := Settings.DB_HOST + ":" + Settings.DB_PORT
|
addr := Settings.DB_HOST + ":" + Settings.DB_PORT
|
||||||
|
|
||||||
|
12
vendor/github.com/beevik/etree/CONTRIBUTORS
generated
vendored
12
vendor/github.com/beevik/etree/CONTRIBUTORS
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
Brett Vickers (beevik)
|
|
||||||
Felix Geisendörfer (felixge)
|
|
||||||
Kamil Kisiel (kisielk)
|
|
||||||
Graham King (grahamking)
|
|
||||||
Matt Smith (ma314smith)
|
|
||||||
Michal Jemala (michaljemala)
|
|
||||||
Nicolas Piganeau (npiganeau)
|
|
||||||
Chris Brown (ccbrown)
|
|
||||||
Earncef Sequeira (earncef)
|
|
||||||
Gabriel de Labachelerie (wuzuf)
|
|
||||||
Martin Dosch (mdosch)
|
|
||||||
Hugo Wetterberg (hugowetterberg)
|
|
24
vendor/github.com/beevik/etree/LICENSE
generated
vendored
24
vendor/github.com/beevik/etree/LICENSE
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
Copyright 2015-2023 Brett Vickers. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. 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.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``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 COPYRIGHT HOLDER 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.
|
|
204
vendor/github.com/beevik/etree/README.md
generated
vendored
204
vendor/github.com/beevik/etree/README.md
generated
vendored
@ -1,204 +0,0 @@
|
|||||||
[](https://godoc.org/github.com/beevik/etree)
|
|
||||||
|
|
||||||
etree
|
|
||||||
=====
|
|
||||||
|
|
||||||
The etree package is a lightweight, pure go package that expresses XML in
|
|
||||||
the form of an element tree. Its design was inspired by the Python
|
|
||||||
[ElementTree](http://docs.python.org/2/library/xml.etree.elementtree.html)
|
|
||||||
module.
|
|
||||||
|
|
||||||
Some of the package's capabilities and features:
|
|
||||||
|
|
||||||
* Represents XML documents as trees of elements for easy traversal.
|
|
||||||
* Imports, serializes, modifies or creates XML documents from scratch.
|
|
||||||
* Writes and reads XML to/from files, byte slices, strings and io interfaces.
|
|
||||||
* Performs simple or complex searches with lightweight XPath-like query APIs.
|
|
||||||
* Auto-indents XML using spaces or tabs for better readability.
|
|
||||||
* Implemented in pure go; depends only on standard go libraries.
|
|
||||||
* Built on top of the go [encoding/xml](http://golang.org/pkg/encoding/xml)
|
|
||||||
package.
|
|
||||||
|
|
||||||
### Creating an XML document
|
|
||||||
|
|
||||||
The following example creates an XML document from scratch using the etree
|
|
||||||
package and outputs its indented contents to stdout.
|
|
||||||
```go
|
|
||||||
doc := etree.NewDocument()
|
|
||||||
doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`)
|
|
||||||
doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`)
|
|
||||||
|
|
||||||
people := doc.CreateElement("People")
|
|
||||||
people.CreateComment("These are all known people")
|
|
||||||
|
|
||||||
jon := people.CreateElement("Person")
|
|
||||||
jon.CreateAttr("name", "Jon")
|
|
||||||
|
|
||||||
sally := people.CreateElement("Person")
|
|
||||||
sally.CreateAttr("name", "Sally")
|
|
||||||
|
|
||||||
doc.Indent(2)
|
|
||||||
doc.WriteTo(os.Stdout)
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
```xml
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
|
|
||||||
<People>
|
|
||||||
<!--These are all known people-->
|
|
||||||
<Person name="Jon"/>
|
|
||||||
<Person name="Sally"/>
|
|
||||||
</People>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reading an XML file
|
|
||||||
|
|
||||||
Suppose you have a file on disk called `bookstore.xml` containing the
|
|
||||||
following data:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<bookstore xmlns:p="urn:schemas-books-com:prices">
|
|
||||||
|
|
||||||
<book category="COOKING">
|
|
||||||
<title lang="en">Everyday Italian</title>
|
|
||||||
<author>Giada De Laurentiis</author>
|
|
||||||
<year>2005</year>
|
|
||||||
<p:price>30.00</p:price>
|
|
||||||
</book>
|
|
||||||
|
|
||||||
<book category="CHILDREN">
|
|
||||||
<title lang="en">Harry Potter</title>
|
|
||||||
<author>J K. Rowling</author>
|
|
||||||
<year>2005</year>
|
|
||||||
<p:price>29.99</p:price>
|
|
||||||
</book>
|
|
||||||
|
|
||||||
<book category="WEB">
|
|
||||||
<title lang="en">XQuery Kick Start</title>
|
|
||||||
<author>James McGovern</author>
|
|
||||||
<author>Per Bothner</author>
|
|
||||||
<author>Kurt Cagle</author>
|
|
||||||
<author>James Linn</author>
|
|
||||||
<author>Vaidyanathan Nagarajan</author>
|
|
||||||
<year>2003</year>
|
|
||||||
<p:price>49.99</p:price>
|
|
||||||
</book>
|
|
||||||
|
|
||||||
<book category="WEB">
|
|
||||||
<title lang="en">Learning XML</title>
|
|
||||||
<author>Erik T. Ray</author>
|
|
||||||
<year>2003</year>
|
|
||||||
<p:price>39.95</p:price>
|
|
||||||
</book>
|
|
||||||
|
|
||||||
</bookstore>
|
|
||||||
```
|
|
||||||
|
|
||||||
This code reads the file's contents into an etree document.
|
|
||||||
```go
|
|
||||||
doc := etree.NewDocument()
|
|
||||||
if err := doc.ReadFromFile("bookstore.xml"); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also read XML from a string, a byte slice, or an `io.Reader`.
|
|
||||||
|
|
||||||
### Processing elements and attributes
|
|
||||||
|
|
||||||
This example illustrates several ways to access elements and attributes using
|
|
||||||
etree selection queries.
|
|
||||||
```go
|
|
||||||
root := doc.SelectElement("bookstore")
|
|
||||||
fmt.Println("ROOT element:", root.Tag)
|
|
||||||
|
|
||||||
for _, book := range root.SelectElements("book") {
|
|
||||||
fmt.Println("CHILD element:", book.Tag)
|
|
||||||
if title := book.SelectElement("title"); title != nil {
|
|
||||||
lang := title.SelectAttrValue("lang", "unknown")
|
|
||||||
fmt.Printf(" TITLE: %s (%s)\n", title.Text(), lang)
|
|
||||||
}
|
|
||||||
for _, attr := range book.Attr {
|
|
||||||
fmt.Printf(" ATTR: %s=%s\n", attr.Key, attr.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Output:
|
|
||||||
```
|
|
||||||
ROOT element: bookstore
|
|
||||||
CHILD element: book
|
|
||||||
TITLE: Everyday Italian (en)
|
|
||||||
ATTR: category=COOKING
|
|
||||||
CHILD element: book
|
|
||||||
TITLE: Harry Potter (en)
|
|
||||||
ATTR: category=CHILDREN
|
|
||||||
CHILD element: book
|
|
||||||
TITLE: XQuery Kick Start (en)
|
|
||||||
ATTR: category=WEB
|
|
||||||
CHILD element: book
|
|
||||||
TITLE: Learning XML (en)
|
|
||||||
ATTR: category=WEB
|
|
||||||
```
|
|
||||||
|
|
||||||
### Path queries
|
|
||||||
|
|
||||||
This example uses etree's path functions to select all book titles that fall
|
|
||||||
into the category of 'WEB'. The double-slash prefix in the path causes the
|
|
||||||
search for book elements to occur recursively; book elements may appear at any
|
|
||||||
level of the XML hierarchy.
|
|
||||||
```go
|
|
||||||
for _, t := range doc.FindElements("//book[@category='WEB']/title") {
|
|
||||||
fmt.Println("Title:", t.Text())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
```
|
|
||||||
Title: XQuery Kick Start
|
|
||||||
Title: Learning XML
|
|
||||||
```
|
|
||||||
|
|
||||||
This example finds the first book element under the root bookstore element and
|
|
||||||
outputs the tag and text of each of its child elements.
|
|
||||||
```go
|
|
||||||
for _, e := range doc.FindElements("./bookstore/book[1]/*") {
|
|
||||||
fmt.Printf("%s: %s\n", e.Tag, e.Text())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
```
|
|
||||||
title: Everyday Italian
|
|
||||||
author: Giada De Laurentiis
|
|
||||||
year: 2005
|
|
||||||
price: 30.00
|
|
||||||
```
|
|
||||||
|
|
||||||
This example finds all books with a price of 49.99 and outputs their titles.
|
|
||||||
```go
|
|
||||||
path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title")
|
|
||||||
for _, e := range doc.FindElementsPath(path) {
|
|
||||||
fmt.Println(e.Text())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
```
|
|
||||||
XQuery Kick Start
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that this example uses the FindElementsPath function, which takes as an
|
|
||||||
argument a pre-compiled path object. Use precompiled paths when you plan to
|
|
||||||
search with the same path more than once.
|
|
||||||
|
|
||||||
### Other features
|
|
||||||
|
|
||||||
These are just a few examples of the things the etree package can do. See the
|
|
||||||
[documentation](http://godoc.org/github.com/beevik/etree) for a complete
|
|
||||||
description of its capabilities.
|
|
||||||
|
|
||||||
### Contributing
|
|
||||||
|
|
||||||
This project accepts contributions. Just fork the repo and submit a pull
|
|
||||||
request!
|
|
153
vendor/github.com/beevik/etree/RELEASE_NOTES.md
generated
vendored
153
vendor/github.com/beevik/etree/RELEASE_NOTES.md
generated
vendored
@ -1,153 +0,0 @@
|
|||||||
Release v1.2.0
|
|
||||||
==============
|
|
||||||
|
|
||||||
**New Features**
|
|
||||||
|
|
||||||
* Add the ability to write XML fragments using Token WriteTo functions.
|
|
||||||
* Add the ability to re-indent an XML element as though it were the root of
|
|
||||||
the document.
|
|
||||||
* Add a ReadSettings option to preserve CDATA blocks when reading and XML
|
|
||||||
document.
|
|
||||||
|
|
||||||
Release v1.1.4
|
|
||||||
==============
|
|
||||||
|
|
||||||
**New Features**
|
|
||||||
|
|
||||||
* Add the ability to preserve whitespace in leaf elements during indent.
|
|
||||||
* Add the ability to suppress a document-trailing newline during indent.
|
|
||||||
* Add choice of XML attribute quoting style (single-quote or double-quote).
|
|
||||||
|
|
||||||
**Removed Features**
|
|
||||||
|
|
||||||
* Removed the CDATA preservation change introduced in v1.1.3. It was
|
|
||||||
implemented in a way that broke the ability to process XML documents
|
|
||||||
encoded using non-UTF8 character sets.
|
|
||||||
|
|
||||||
Release v1.1.3
|
|
||||||
==============
|
|
||||||
|
|
||||||
* XML reads now preserve CDATA sections instead of converting them to
|
|
||||||
standard character data.
|
|
||||||
|
|
||||||
Release v1.1.2
|
|
||||||
==============
|
|
||||||
|
|
||||||
* Fixed a path parsing bug.
|
|
||||||
* The `Element.Text` function now handles comments embedded between
|
|
||||||
character data spans.
|
|
||||||
|
|
||||||
Release v1.1.1
|
|
||||||
==============
|
|
||||||
|
|
||||||
* Updated go version in `go.mod` to 1.20
|
|
||||||
|
|
||||||
Release v1.1.0
|
|
||||||
==============
|
|
||||||
|
|
||||||
**New Features**
|
|
||||||
|
|
||||||
* New attribute helpers.
|
|
||||||
* Added the `Element.SortAttrs` method, which lexicographically sorts an
|
|
||||||
element's attributes by key.
|
|
||||||
* New `ReadSettings` properties.
|
|
||||||
* Added `Entity` for the support of custom entity maps.
|
|
||||||
* New `WriteSettings` properties.
|
|
||||||
* Added `UseCRLF` to allow the output of CR-LF newlines instead of the
|
|
||||||
default LF newlines. This is useful on Windows systems.
|
|
||||||
* Additional support for text and CDATA sections.
|
|
||||||
* The `Element.Text` method now returns the concatenation of all consecutive
|
|
||||||
character data tokens immediately following an element's opening tag.
|
|
||||||
* Added `Element.SetCData` to replace the character data immediately
|
|
||||||
following an element's opening tag with a CDATA section.
|
|
||||||
* Added `Element.CreateCData` to create and add a CDATA section child
|
|
||||||
`CharData` token to an element.
|
|
||||||
* Added `Element.CreateText` to create and add a child text `CharData` token
|
|
||||||
to an element.
|
|
||||||
* Added `NewCData` to create a parentless CDATA section `CharData` token.
|
|
||||||
* Added `NewText` to create a parentless text `CharData`
|
|
||||||
token.
|
|
||||||
* Added `CharData.IsCData` to detect if the token contains a CDATA section.
|
|
||||||
* Added `CharData.IsWhitespace` to detect if the token contains whitespace
|
|
||||||
inserted by one of the document Indent functions.
|
|
||||||
* Modified `Element.SetText` so that it replaces a run of consecutive
|
|
||||||
character data tokens following the element's opening tag (instead of just
|
|
||||||
the first one).
|
|
||||||
* New "tail text" support.
|
|
||||||
* Added the `Element.Tail` method, which returns the text immediately
|
|
||||||
following an element's closing tag.
|
|
||||||
* Added the `Element.SetTail` method, which modifies the text immediately
|
|
||||||
following an element's closing tag.
|
|
||||||
* New element child insertion and removal methods.
|
|
||||||
* Added the `Element.InsertChildAt` method, which inserts a new child token
|
|
||||||
before the specified child token index.
|
|
||||||
* Added the `Element.RemoveChildAt` method, which removes the child token at
|
|
||||||
the specified child token index.
|
|
||||||
* New element and attribute queries.
|
|
||||||
* Added the `Element.Index` method, which returns the element's index within
|
|
||||||
its parent element's child token list.
|
|
||||||
* Added the `Element.NamespaceURI` method to return the namespace URI
|
|
||||||
associated with an element.
|
|
||||||
* Added the `Attr.NamespaceURI` method to return the namespace URI
|
|
||||||
associated with an element.
|
|
||||||
* Added the `Attr.Element` method to return the element that an attribute
|
|
||||||
belongs to.
|
|
||||||
* New Path filter functions.
|
|
||||||
* Added `[local-name()='val']` to keep elements whose unprefixed tag matches
|
|
||||||
the desired value.
|
|
||||||
* Added `[name()='val']` to keep elements whose full tag matches the desired
|
|
||||||
value.
|
|
||||||
* Added `[namespace-prefix()='val']` to keep elements whose namespace prefix
|
|
||||||
matches the desired value.
|
|
||||||
* Added `[namespace-uri()='val']` to keep elements whose namespace URI
|
|
||||||
matches the desired value.
|
|
||||||
|
|
||||||
**Bug Fixes**
|
|
||||||
|
|
||||||
* A default XML `CharSetReader` is now used to prevent failed parsing of XML
|
|
||||||
documents using certain encodings.
|
|
||||||
([Issue](https://github.com/beevik/etree/issues/53)).
|
|
||||||
* All characters are now properly escaped according to XML parsing rules.
|
|
||||||
([Issue](https://github.com/beevik/etree/issues/55)).
|
|
||||||
* The `Document.Indent` and `Document.IndentTabs` functions no longer insert
|
|
||||||
empty string `CharData` tokens.
|
|
||||||
|
|
||||||
**Deprecated**
|
|
||||||
|
|
||||||
* `Element`
|
|
||||||
* The `InsertChild` method is deprecated. Use `InsertChildAt` instead.
|
|
||||||
* The `CreateCharData` method is deprecated. Use `CreateText` instead.
|
|
||||||
* `CharData`
|
|
||||||
* The `NewCharData` method is deprecated. Use `NewText` instead.
|
|
||||||
|
|
||||||
|
|
||||||
Release v1.0.1
|
|
||||||
==============
|
|
||||||
|
|
||||||
**Changes**
|
|
||||||
|
|
||||||
* Added support for absolute etree Path queries. An absolute path begins with
|
|
||||||
`/` or `//` and begins its search from the element's document root.
|
|
||||||
* Added [`GetPath`](https://godoc.org/github.com/beevik/etree#Element.GetPath)
|
|
||||||
and [`GetRelativePath`](https://godoc.org/github.com/beevik/etree#Element.GetRelativePath)
|
|
||||||
functions to the [`Element`](https://godoc.org/github.com/beevik/etree#Element)
|
|
||||||
type.
|
|
||||||
|
|
||||||
**Breaking changes**
|
|
||||||
|
|
||||||
* A path starting with `//` is now interpreted as an absolute path.
|
|
||||||
Previously, it was interpreted as a relative path starting from the element
|
|
||||||
whose
|
|
||||||
[`FindElement`](https://godoc.org/github.com/beevik/etree#Element.FindElement)
|
|
||||||
method was called. To remain compatible with this release, all paths
|
|
||||||
prefixed with `//` should be prefixed with `.//` when called from any
|
|
||||||
element other than the document's root.
|
|
||||||
* [**edit 2/1/2019**]: Minor releases should not contain breaking changes.
|
|
||||||
Even though this breaking change was very minor, it was a mistake to include
|
|
||||||
it in this minor release. In the future, all breaking changes will be
|
|
||||||
limited to major releases (e.g., version 2.0.0).
|
|
||||||
|
|
||||||
Release v1.0.0
|
|
||||||
==============
|
|
||||||
|
|
||||||
Initial release.
|
|
1666
vendor/github.com/beevik/etree/etree.go
generated
vendored
1666
vendor/github.com/beevik/etree/etree.go
generated
vendored
File diff suppressed because it is too large
Load Diff
394
vendor/github.com/beevik/etree/helpers.go
generated
vendored
394
vendor/github.com/beevik/etree/helpers.go
generated
vendored
@ -1,394 +0,0 @@
|
|||||||
// Copyright 2015-2019 Brett Vickers.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package etree
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A simple stack
|
|
||||||
type stack struct {
|
|
||||||
data []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stack) empty() bool {
|
|
||||||
return len(s.data) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stack) push(value interface{}) {
|
|
||||||
s.data = append(s.data, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stack) pop() interface{} {
|
|
||||||
value := s.data[len(s.data)-1]
|
|
||||||
s.data[len(s.data)-1] = nil
|
|
||||||
s.data = s.data[:len(s.data)-1]
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stack) peek() interface{} {
|
|
||||||
return s.data[len(s.data)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// A fifo is a simple first-in-first-out queue.
|
|
||||||
type fifo struct {
|
|
||||||
data []interface{}
|
|
||||||
head, tail int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fifo) add(value interface{}) {
|
|
||||||
if f.len()+1 >= len(f.data) {
|
|
||||||
f.grow()
|
|
||||||
}
|
|
||||||
f.data[f.tail] = value
|
|
||||||
if f.tail++; f.tail == len(f.data) {
|
|
||||||
f.tail = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fifo) remove() interface{} {
|
|
||||||
value := f.data[f.head]
|
|
||||||
f.data[f.head] = nil
|
|
||||||
if f.head++; f.head == len(f.data) {
|
|
||||||
f.head = 0
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fifo) len() int {
|
|
||||||
if f.tail >= f.head {
|
|
||||||
return f.tail - f.head
|
|
||||||
}
|
|
||||||
return len(f.data) - f.head + f.tail
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fifo) grow() {
|
|
||||||
c := len(f.data) * 2
|
|
||||||
if c == 0 {
|
|
||||||
c = 4
|
|
||||||
}
|
|
||||||
buf, count := make([]interface{}, c), f.len()
|
|
||||||
if f.tail >= f.head {
|
|
||||||
copy(buf[0:count], f.data[f.head:f.tail])
|
|
||||||
} else {
|
|
||||||
hindex := len(f.data) - f.head
|
|
||||||
copy(buf[0:hindex], f.data[f.head:])
|
|
||||||
copy(buf[hindex:count], f.data[:f.tail])
|
|
||||||
}
|
|
||||||
f.data, f.head, f.tail = buf, 0, count
|
|
||||||
}
|
|
||||||
|
|
||||||
// xmlReader provides the interface by which an XML byte stream is
|
|
||||||
// processed and decoded.
|
|
||||||
type xmlReader interface {
|
|
||||||
Bytes() int64
|
|
||||||
Read(p []byte) (n int, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// xmlSimpleReader implements a proxy reader that counts the number of
|
|
||||||
// bytes read from its encapsulated reader.
|
|
||||||
type xmlSimpleReader struct {
|
|
||||||
r io.Reader
|
|
||||||
bytes int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func newXmlSimpleReader(r io.Reader) xmlReader {
|
|
||||||
return &xmlSimpleReader{r, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlSimpleReader) Bytes() int64 {
|
|
||||||
return xr.bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlSimpleReader) Read(p []byte) (n int, err error) {
|
|
||||||
n, err = xr.r.Read(p)
|
|
||||||
xr.bytes += int64(n)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// xmlPeekReader implements a proxy reader that counts the number of
|
|
||||||
// bytes read from its encapsulated reader. It also allows the caller to
|
|
||||||
// "peek" at the previous portions of the buffer after they have been
|
|
||||||
// parsed.
|
|
||||||
type xmlPeekReader struct {
|
|
||||||
r io.Reader
|
|
||||||
bytes int64 // total bytes read by the Read function
|
|
||||||
buf []byte // internal read buffer
|
|
||||||
bufSize int // total bytes used in the read buffer
|
|
||||||
bufOffset int64 // total bytes read when buf was last filled
|
|
||||||
window []byte // current read buffer window
|
|
||||||
peekBuf []byte // buffer used to store data to be peeked at later
|
|
||||||
peekOffset int64 // total read offset of the start of the peek buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func newXmlPeekReader(r io.Reader) *xmlPeekReader {
|
|
||||||
buf := make([]byte, 4096)
|
|
||||||
return &xmlPeekReader{
|
|
||||||
r: r,
|
|
||||||
bytes: 0,
|
|
||||||
buf: buf,
|
|
||||||
bufSize: 0,
|
|
||||||
bufOffset: 0,
|
|
||||||
window: buf[0:0],
|
|
||||||
peekBuf: make([]byte, 0),
|
|
||||||
peekOffset: -1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) Bytes() int64 {
|
|
||||||
return xr.bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) Read(p []byte) (n int, err error) {
|
|
||||||
if len(xr.window) == 0 {
|
|
||||||
err = xr.fill()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if len(xr.window) == 0 {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(xr.window) < len(p) {
|
|
||||||
n = len(xr.window)
|
|
||||||
} else {
|
|
||||||
n = len(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, xr.window)
|
|
||||||
xr.window = xr.window[n:]
|
|
||||||
xr.bytes += int64(n)
|
|
||||||
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) PeekPrepare(offset int64, maxLen int) {
|
|
||||||
if maxLen > cap(xr.peekBuf) {
|
|
||||||
xr.peekBuf = make([]byte, 0, maxLen)
|
|
||||||
}
|
|
||||||
xr.peekBuf = xr.peekBuf[0:0]
|
|
||||||
xr.peekOffset = offset
|
|
||||||
xr.updatePeekBuf()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) PeekFinalize() []byte {
|
|
||||||
xr.updatePeekBuf()
|
|
||||||
return xr.peekBuf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) fill() error {
|
|
||||||
xr.bufOffset = xr.bytes
|
|
||||||
xr.bufSize = 0
|
|
||||||
n, err := xr.r.Read(xr.buf)
|
|
||||||
if err != nil {
|
|
||||||
xr.window, xr.bufSize = xr.buf[0:0], 0
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
xr.window, xr.bufSize = xr.buf[:n], n
|
|
||||||
xr.updatePeekBuf()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xr *xmlPeekReader) updatePeekBuf() {
|
|
||||||
peekRemain := cap(xr.peekBuf) - len(xr.peekBuf)
|
|
||||||
if xr.peekOffset >= 0 && peekRemain > 0 {
|
|
||||||
rangeMin := xr.peekOffset
|
|
||||||
rangeMax := xr.peekOffset + int64(cap(xr.peekBuf))
|
|
||||||
bufMin := xr.bufOffset
|
|
||||||
bufMax := xr.bufOffset + int64(xr.bufSize)
|
|
||||||
if rangeMin < bufMin {
|
|
||||||
rangeMin = bufMin
|
|
||||||
}
|
|
||||||
if rangeMax > bufMax {
|
|
||||||
rangeMax = bufMax
|
|
||||||
}
|
|
||||||
if rangeMax > rangeMin {
|
|
||||||
rangeMin -= xr.bufOffset
|
|
||||||
rangeMax -= xr.bufOffset
|
|
||||||
if int(rangeMax-rangeMin) > peekRemain {
|
|
||||||
rangeMax = rangeMin + int64(peekRemain)
|
|
||||||
}
|
|
||||||
xr.peekBuf = append(xr.peekBuf, xr.buf[rangeMin:rangeMax]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xmlWriter implements a proxy writer that counts the number of
|
|
||||||
// bytes written by its encapsulated writer.
|
|
||||||
type xmlWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
bytes int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func newXmlWriter(w io.Writer) *xmlWriter {
|
|
||||||
return &xmlWriter{w: w}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (xw *xmlWriter) Write(p []byte) (n int, err error) {
|
|
||||||
n, err = xw.w.Write(p)
|
|
||||||
xw.bytes += int64(n)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWhitespace returns true if the byte slice contains only
|
|
||||||
// whitespace characters.
|
|
||||||
func isWhitespace(s string) bool {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if c := s[i]; c != ' ' && c != '\t' && c != '\n' && c != '\r' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// spaceMatch returns true if namespace a is the empty string
|
|
||||||
// or if namespace a equals namespace b.
|
|
||||||
func spaceMatch(a, b string) bool {
|
|
||||||
switch {
|
|
||||||
case a == "":
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return a == b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// spaceDecompose breaks a namespace:tag identifier at the ':'
|
|
||||||
// and returns the two parts.
|
|
||||||
func spaceDecompose(str string) (space, key string) {
|
|
||||||
colon := strings.IndexByte(str, ':')
|
|
||||||
if colon == -1 {
|
|
||||||
return "", str
|
|
||||||
}
|
|
||||||
return str[:colon], str[colon+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strings used by indentCRLF and indentLF
|
|
||||||
const (
|
|
||||||
indentSpaces = "\r\n "
|
|
||||||
indentTabs = "\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
|
|
||||||
)
|
|
||||||
|
|
||||||
// indentCRLF returns a CRLF newline followed by n copies of the first
|
|
||||||
// non-CRLF character in the source string.
|
|
||||||
func indentCRLF(n int, source string) string {
|
|
||||||
switch {
|
|
||||||
case n < 0:
|
|
||||||
return source[:2]
|
|
||||||
case n < len(source)-1:
|
|
||||||
return source[:n+2]
|
|
||||||
default:
|
|
||||||
return source + strings.Repeat(source[2:3], n-len(source)+2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// indentLF returns a LF newline followed by n copies of the first non-LF
|
|
||||||
// character in the source string.
|
|
||||||
func indentLF(n int, source string) string {
|
|
||||||
switch {
|
|
||||||
case n < 0:
|
|
||||||
return source[1:2]
|
|
||||||
case n < len(source)-1:
|
|
||||||
return source[1 : n+2]
|
|
||||||
default:
|
|
||||||
return source[1:] + strings.Repeat(source[2:3], n-len(source)+2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nextIndex returns the index of the next occurrence of sep in s,
|
|
||||||
// starting from offset. It returns -1 if the sep string is not found.
|
|
||||||
func nextIndex(s, sep string, offset int) int {
|
|
||||||
switch i := strings.Index(s[offset:], sep); i {
|
|
||||||
case -1:
|
|
||||||
return -1
|
|
||||||
default:
|
|
||||||
return offset + i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isInteger returns true if the string s contains an integer.
|
|
||||||
func isInteger(s string) bool {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if (s[i] < '0' || s[i] > '9') && !(i == 0 && s[i] == '-') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type escapeMode byte
|
|
||||||
|
|
||||||
const (
|
|
||||||
escapeNormal escapeMode = iota
|
|
||||||
escapeCanonicalText
|
|
||||||
escapeCanonicalAttr
|
|
||||||
)
|
|
||||||
|
|
||||||
// escapeString writes an escaped version of a string to the writer.
|
|
||||||
func escapeString(w Writer, s string, m escapeMode) {
|
|
||||||
var esc []byte
|
|
||||||
last := 0
|
|
||||||
for i := 0; i < len(s); {
|
|
||||||
r, width := utf8.DecodeRuneInString(s[i:])
|
|
||||||
i += width
|
|
||||||
switch r {
|
|
||||||
case '&':
|
|
||||||
esc = []byte("&")
|
|
||||||
case '<':
|
|
||||||
esc = []byte("<")
|
|
||||||
case '>':
|
|
||||||
if m == escapeCanonicalAttr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte(">")
|
|
||||||
case '\'':
|
|
||||||
if m != escapeNormal {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte("'")
|
|
||||||
case '"':
|
|
||||||
if m == escapeCanonicalText {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte(""")
|
|
||||||
case '\t':
|
|
||||||
if m != escapeCanonicalAttr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte("	")
|
|
||||||
case '\n':
|
|
||||||
if m != escapeCanonicalAttr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte("
")
|
|
||||||
case '\r':
|
|
||||||
if m == escapeNormal {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
esc = []byte("
")
|
|
||||||
default:
|
|
||||||
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
|
|
||||||
esc = []byte("\uFFFD")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
w.WriteString(s[last : i-width])
|
|
||||||
w.Write(esc)
|
|
||||||
last = i
|
|
||||||
}
|
|
||||||
w.WriteString(s[last:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func isInCharacterRange(r rune) bool {
|
|
||||||
return r == 0x09 ||
|
|
||||||
r == 0x0A ||
|
|
||||||
r == 0x0D ||
|
|
||||||
r >= 0x20 && r <= 0xD7FF ||
|
|
||||||
r >= 0xE000 && r <= 0xFFFD ||
|
|
||||||
r >= 0x10000 && r <= 0x10FFFF
|
|
||||||
}
|
|
586
vendor/github.com/beevik/etree/path.go
generated
vendored
586
vendor/github.com/beevik/etree/path.go
generated
vendored
@ -1,586 +0,0 @@
|
|||||||
// Copyright 2015-2019 Brett Vickers.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package etree
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
A Path is a string that represents a search path through an etree starting
|
|
||||||
from the document root or an arbitrary element. Paths are used with the
|
|
||||||
Element object's Find* methods to locate and return desired elements.
|
|
||||||
|
|
||||||
A Path consists of a series of slash-separated "selectors", each of which may
|
|
||||||
be modified by one or more bracket-enclosed "filters". Selectors are used to
|
|
||||||
traverse the etree from element to element, while filters are used to narrow
|
|
||||||
the list of candidate elements at each node.
|
|
||||||
|
|
||||||
Although etree Path strings are structurally and behaviorally similar to XPath
|
|
||||||
strings (https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more
|
|
||||||
limited set of selectors and filtering options.
|
|
||||||
|
|
||||||
The following selectors are supported by etree paths:
|
|
||||||
|
|
||||||
. Select the current element.
|
|
||||||
.. Select the parent of the current element.
|
|
||||||
* Select all child elements of the current element.
|
|
||||||
/ Select the root element when used at the start of a path.
|
|
||||||
// Select all descendants of the current element.
|
|
||||||
tag Select all child elements with a name matching the tag.
|
|
||||||
|
|
||||||
The following basic filters are supported:
|
|
||||||
|
|
||||||
[@attrib] Keep elements with an attribute named attrib.
|
|
||||||
[@attrib='val'] Keep elements with an attribute named attrib and value matching val.
|
|
||||||
[tag] Keep elements with a child element named tag.
|
|
||||||
[tag='val'] Keep elements with a child element named tag and text matching val.
|
|
||||||
[n] Keep the n-th element, where n is a numeric index starting from 1.
|
|
||||||
|
|
||||||
The following function-based filters are supported:
|
|
||||||
|
|
||||||
[text()] Keep elements with non-empty text.
|
|
||||||
[text()='val'] Keep elements whose text matches val.
|
|
||||||
[local-name()='val'] Keep elements whose un-prefixed tag matches val.
|
|
||||||
[name()='val'] Keep elements whose full tag exactly matches val.
|
|
||||||
[namespace-prefix()] Keep elements with non-empty namespace prefixes.
|
|
||||||
[namespace-prefix()='val'] Keep elements whose namespace prefix matches val.
|
|
||||||
[namespace-uri()] Keep elements with non-empty namespace URIs.
|
|
||||||
[namespace-uri()='val'] Keep elements whose namespace URI matches val.
|
|
||||||
|
|
||||||
Below are some examples of etree path strings.
|
|
||||||
|
|
||||||
Select the bookstore child element of the root element:
|
|
||||||
|
|
||||||
/bookstore
|
|
||||||
|
|
||||||
Beginning from the root element, select the title elements of all descendant
|
|
||||||
book elements having a 'category' attribute of 'WEB':
|
|
||||||
|
|
||||||
//book[@category='WEB']/title
|
|
||||||
|
|
||||||
Beginning from the current element, select the first descendant book element
|
|
||||||
with a title child element containing the text 'Great Expectations':
|
|
||||||
|
|
||||||
.//book[title='Great Expectations'][1]
|
|
||||||
|
|
||||||
Beginning from the current element, select all child elements of book elements
|
|
||||||
with an attribute 'language' set to 'english':
|
|
||||||
|
|
||||||
./book/*[@language='english']
|
|
||||||
|
|
||||||
Beginning from the current element, select all child elements of book elements
|
|
||||||
containing the text 'special':
|
|
||||||
|
|
||||||
./book/*[text()='special']
|
|
||||||
|
|
||||||
Beginning from the current element, select all descendant book elements whose
|
|
||||||
title child element has a 'language' attribute of 'french':
|
|
||||||
|
|
||||||
.//book/title[@language='french']/..
|
|
||||||
|
|
||||||
Beginning from the current element, select all descendant book elements
|
|
||||||
belonging to the http://www.w3.org/TR/html4/ namespace:
|
|
||||||
|
|
||||||
.//book[namespace-uri()='http://www.w3.org/TR/html4/']
|
|
||||||
*/
|
|
||||||
type Path struct {
|
|
||||||
segments []segment
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrPath is returned by path functions when an invalid etree path is provided.
|
|
||||||
type ErrPath string
|
|
||||||
|
|
||||||
// Error returns the string describing a path error.
|
|
||||||
func (err ErrPath) Error() string {
|
|
||||||
return "etree: " + string(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompilePath creates an optimized version of an XPath-like string that
|
|
||||||
// can be used to query elements in an element tree.
|
|
||||||
func CompilePath(path string) (Path, error) {
|
|
||||||
var comp compiler
|
|
||||||
segments := comp.parsePath(path)
|
|
||||||
if comp.err != ErrPath("") {
|
|
||||||
return Path{nil}, comp.err
|
|
||||||
}
|
|
||||||
return Path{segments}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustCompilePath creates an optimized version of an XPath-like string that
|
|
||||||
// can be used to query elements in an element tree. Panics if an error
|
|
||||||
// occurs. Use this function to create Paths when you know the path is
|
|
||||||
// valid (i.e., if it's hard-coded).
|
|
||||||
func MustCompilePath(path string) Path {
|
|
||||||
p, err := CompilePath(path)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// A segment is a portion of a path between "/" characters.
|
|
||||||
// It contains one selector and zero or more [filters].
|
|
||||||
type segment struct {
|
|
||||||
sel selector
|
|
||||||
filters []filter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (seg *segment) apply(e *Element, p *pather) {
|
|
||||||
seg.sel.apply(e, p)
|
|
||||||
for _, f := range seg.filters {
|
|
||||||
f.apply(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A selector selects XML elements for consideration by the
|
|
||||||
// path traversal.
|
|
||||||
type selector interface {
|
|
||||||
apply(e *Element, p *pather)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A filter pares down a list of candidate XML elements based
|
|
||||||
// on a path filter in [brackets].
|
|
||||||
type filter interface {
|
|
||||||
apply(p *pather)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A pather is helper object that traverses an element tree using
|
|
||||||
// a Path object. It collects and deduplicates all elements matching
|
|
||||||
// the path query.
|
|
||||||
type pather struct {
|
|
||||||
queue fifo
|
|
||||||
results []*Element
|
|
||||||
inResults map[*Element]bool
|
|
||||||
candidates []*Element
|
|
||||||
scratch []*Element // used by filters
|
|
||||||
}
|
|
||||||
|
|
||||||
// A node represents an element and the remaining path segments that
|
|
||||||
// should be applied against it by the pather.
|
|
||||||
type node struct {
|
|
||||||
e *Element
|
|
||||||
segments []segment
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPather() *pather {
|
|
||||||
return &pather{
|
|
||||||
results: make([]*Element, 0),
|
|
||||||
inResults: make(map[*Element]bool),
|
|
||||||
candidates: make([]*Element, 0),
|
|
||||||
scratch: make([]*Element, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// traverse follows the path from the element e, collecting
|
|
||||||
// and then returning all elements that match the path's selectors
|
|
||||||
// and filters.
|
|
||||||
func (p *pather) traverse(e *Element, path Path) []*Element {
|
|
||||||
for p.queue.add(node{e, path.segments}); p.queue.len() > 0; {
|
|
||||||
p.eval(p.queue.remove().(node))
|
|
||||||
}
|
|
||||||
return p.results
|
|
||||||
}
|
|
||||||
|
|
||||||
// eval evaluates the current path node by applying the remaining
|
|
||||||
// path's selector rules against the node's element.
|
|
||||||
func (p *pather) eval(n node) {
|
|
||||||
p.candidates = p.candidates[0:0]
|
|
||||||
seg, remain := n.segments[0], n.segments[1:]
|
|
||||||
seg.apply(n.e, p)
|
|
||||||
|
|
||||||
if len(remain) == 0 {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
if in := p.inResults[c]; !in {
|
|
||||||
p.inResults[c] = true
|
|
||||||
p.results = append(p.results, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
p.queue.add(node{c, remain})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A compiler generates a compiled path from a path string.
|
|
||||||
type compiler struct {
|
|
||||||
err ErrPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsePath parses an XPath-like string describing a path
|
|
||||||
// through an element tree and returns a slice of segment
|
|
||||||
// descriptors.
|
|
||||||
func (c *compiler) parsePath(path string) []segment {
|
|
||||||
// If path ends with //, fix it
|
|
||||||
if strings.HasSuffix(path, "//") {
|
|
||||||
path += "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
var segments []segment
|
|
||||||
|
|
||||||
// Check for an absolute path
|
|
||||||
if strings.HasPrefix(path, "/") {
|
|
||||||
segments = append(segments, segment{new(selectRoot), []filter{}})
|
|
||||||
path = path[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split path into segments
|
|
||||||
for _, s := range splitPath(path) {
|
|
||||||
segments = append(segments, c.parseSegment(s))
|
|
||||||
if c.err != ErrPath("") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return segments
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitPath(path string) []string {
|
|
||||||
var pieces []string
|
|
||||||
start := 0
|
|
||||||
inquote := false
|
|
||||||
for i := 0; i+1 <= len(path); i++ {
|
|
||||||
if path[i] == '\'' {
|
|
||||||
inquote = !inquote
|
|
||||||
} else if path[i] == '/' && !inquote {
|
|
||||||
pieces = append(pieces, path[start:i])
|
|
||||||
start = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return append(pieces, path[start:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseSegment parses a path segment between / characters.
|
|
||||||
func (c *compiler) parseSegment(path string) segment {
|
|
||||||
pieces := strings.Split(path, "[")
|
|
||||||
seg := segment{
|
|
||||||
sel: c.parseSelector(pieces[0]),
|
|
||||||
filters: []filter{},
|
|
||||||
}
|
|
||||||
for i := 1; i < len(pieces); i++ {
|
|
||||||
fpath := pieces[i]
|
|
||||||
if len(fpath) == 0 || fpath[len(fpath)-1] != ']' {
|
|
||||||
c.err = ErrPath("path has invalid filter [brackets].")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
seg.filters = append(seg.filters, c.parseFilter(fpath[:len(fpath)-1]))
|
|
||||||
}
|
|
||||||
return seg
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseSelector parses a selector at the start of a path segment.
|
|
||||||
func (c *compiler) parseSelector(path string) selector {
|
|
||||||
switch path {
|
|
||||||
case ".":
|
|
||||||
return new(selectSelf)
|
|
||||||
case "..":
|
|
||||||
return new(selectParent)
|
|
||||||
case "*":
|
|
||||||
return new(selectChildren)
|
|
||||||
case "":
|
|
||||||
return new(selectDescendants)
|
|
||||||
default:
|
|
||||||
return newSelectChildrenByTag(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fnTable = map[string]func(e *Element) string{
|
|
||||||
"local-name": (*Element).name,
|
|
||||||
"name": (*Element).FullTag,
|
|
||||||
"namespace-prefix": (*Element).namespacePrefix,
|
|
||||||
"namespace-uri": (*Element).NamespaceURI,
|
|
||||||
"text": (*Element).Text,
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseFilter parses a path filter contained within [brackets].
|
|
||||||
func (c *compiler) parseFilter(path string) filter {
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.err = ErrPath("path contains an empty filter expression.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter contains [@attr='val'], [fn()='val'], or [tag='val']?
|
|
||||||
eqindex := strings.Index(path, "='")
|
|
||||||
if eqindex >= 0 {
|
|
||||||
rindex := nextIndex(path, "'", eqindex+2)
|
|
||||||
if rindex != len(path)-1 {
|
|
||||||
c.err = ErrPath("path has mismatched filter quotes.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
key := path[:eqindex]
|
|
||||||
value := path[eqindex+2 : rindex]
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case key[0] == '@':
|
|
||||||
return newFilterAttrVal(key[1:], value)
|
|
||||||
case strings.HasSuffix(key, "()"):
|
|
||||||
name := key[:len(key)-2]
|
|
||||||
if fn, ok := fnTable[name]; ok {
|
|
||||||
return newFilterFuncVal(fn, value)
|
|
||||||
}
|
|
||||||
c.err = ErrPath("path has unknown function " + name)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return newFilterChildText(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter contains [@attr], [N], [tag] or [fn()]
|
|
||||||
switch {
|
|
||||||
case path[0] == '@':
|
|
||||||
return newFilterAttr(path[1:])
|
|
||||||
case strings.HasSuffix(path, "()"):
|
|
||||||
name := path[:len(path)-2]
|
|
||||||
if fn, ok := fnTable[name]; ok {
|
|
||||||
return newFilterFunc(fn)
|
|
||||||
}
|
|
||||||
c.err = ErrPath("path has unknown function " + name)
|
|
||||||
return nil
|
|
||||||
case isInteger(path):
|
|
||||||
pos, _ := strconv.Atoi(path)
|
|
||||||
switch {
|
|
||||||
case pos > 0:
|
|
||||||
return newFilterPos(pos - 1)
|
|
||||||
default:
|
|
||||||
return newFilterPos(pos)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return newFilterChild(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectSelf selects the current element into the candidate list.
|
|
||||||
type selectSelf struct{}
|
|
||||||
|
|
||||||
func (s *selectSelf) apply(e *Element, p *pather) {
|
|
||||||
p.candidates = append(p.candidates, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectRoot selects the element's root node.
|
|
||||||
type selectRoot struct{}
|
|
||||||
|
|
||||||
func (s *selectRoot) apply(e *Element, p *pather) {
|
|
||||||
root := e
|
|
||||||
for root.parent != nil {
|
|
||||||
root = root.parent
|
|
||||||
}
|
|
||||||
p.candidates = append(p.candidates, root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectParent selects the element's parent into the candidate list.
|
|
||||||
type selectParent struct{}
|
|
||||||
|
|
||||||
func (s *selectParent) apply(e *Element, p *pather) {
|
|
||||||
if e.parent != nil {
|
|
||||||
p.candidates = append(p.candidates, e.parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectChildren selects the element's child elements into the
|
|
||||||
// candidate list.
|
|
||||||
type selectChildren struct{}
|
|
||||||
|
|
||||||
func (s *selectChildren) apply(e *Element, p *pather) {
|
|
||||||
for _, c := range e.Child {
|
|
||||||
if c, ok := c.(*Element); ok {
|
|
||||||
p.candidates = append(p.candidates, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectDescendants selects all descendant child elements
|
|
||||||
// of the element into the candidate list.
|
|
||||||
type selectDescendants struct{}
|
|
||||||
|
|
||||||
func (s *selectDescendants) apply(e *Element, p *pather) {
|
|
||||||
var queue fifo
|
|
||||||
for queue.add(e); queue.len() > 0; {
|
|
||||||
e := queue.remove().(*Element)
|
|
||||||
p.candidates = append(p.candidates, e)
|
|
||||||
for _, c := range e.Child {
|
|
||||||
if c, ok := c.(*Element); ok {
|
|
||||||
queue.add(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// selectChildrenByTag selects into the candidate list all child
|
|
||||||
// elements of the element having the specified tag.
|
|
||||||
type selectChildrenByTag struct {
|
|
||||||
space, tag string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSelectChildrenByTag(path string) *selectChildrenByTag {
|
|
||||||
s, l := spaceDecompose(path)
|
|
||||||
return &selectChildrenByTag{s, l}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *selectChildrenByTag) apply(e *Element, p *pather) {
|
|
||||||
for _, c := range e.Child {
|
|
||||||
if c, ok := c.(*Element); ok && spaceMatch(s.space, c.Space) && s.tag == c.Tag {
|
|
||||||
p.candidates = append(p.candidates, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterPos filters the candidate list, keeping only the
|
|
||||||
// candidate at the specified index.
|
|
||||||
type filterPos struct {
|
|
||||||
index int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterPos(pos int) *filterPos {
|
|
||||||
return &filterPos{pos}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterPos) apply(p *pather) {
|
|
||||||
if f.index >= 0 {
|
|
||||||
if f.index < len(p.candidates) {
|
|
||||||
p.scratch = append(p.scratch, p.candidates[f.index])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if -f.index <= len(p.candidates) {
|
|
||||||
p.scratch = append(p.scratch, p.candidates[len(p.candidates)+f.index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterAttr filters the candidate list for elements having
|
|
||||||
// the specified attribute.
|
|
||||||
type filterAttr struct {
|
|
||||||
space, key string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterAttr(str string) *filterAttr {
|
|
||||||
s, l := spaceDecompose(str)
|
|
||||||
return &filterAttr{s, l}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterAttr) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
for _, a := range c.Attr {
|
|
||||||
if spaceMatch(f.space, a.Space) && f.key == a.Key {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterAttrVal filters the candidate list for elements having
|
|
||||||
// the specified attribute with the specified value.
|
|
||||||
type filterAttrVal struct {
|
|
||||||
space, key, val string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterAttrVal(str, value string) *filterAttrVal {
|
|
||||||
s, l := spaceDecompose(str)
|
|
||||||
return &filterAttrVal{s, l, value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterAttrVal) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
for _, a := range c.Attr {
|
|
||||||
if spaceMatch(f.space, a.Space) && f.key == a.Key && f.val == a.Value {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterFunc filters the candidate list for elements satisfying a custom
|
|
||||||
// boolean function.
|
|
||||||
type filterFunc struct {
|
|
||||||
fn func(e *Element) string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterFunc(fn func(e *Element) string) *filterFunc {
|
|
||||||
return &filterFunc{fn}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterFunc) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
if f.fn(c) != "" {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterFuncVal filters the candidate list for elements containing a value
|
|
||||||
// matching the result of a custom function.
|
|
||||||
type filterFuncVal struct {
|
|
||||||
fn func(e *Element) string
|
|
||||||
val string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterFuncVal(fn func(e *Element) string, value string) *filterFuncVal {
|
|
||||||
return &filterFuncVal{fn, value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterFuncVal) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
if f.fn(c) == f.val {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterChild filters the candidate list for elements having
|
|
||||||
// a child element with the specified tag.
|
|
||||||
type filterChild struct {
|
|
||||||
space, tag string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterChild(str string) *filterChild {
|
|
||||||
s, l := spaceDecompose(str)
|
|
||||||
return &filterChild{s, l}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterChild) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
for _, cc := range c.Child {
|
|
||||||
if cc, ok := cc.(*Element); ok &&
|
|
||||||
spaceMatch(f.space, cc.Space) &&
|
|
||||||
f.tag == cc.Tag {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterChildText filters the candidate list for elements having
|
|
||||||
// a child element with the specified tag and text.
|
|
||||||
type filterChildText struct {
|
|
||||||
space, tag, text string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterChildText(str, text string) *filterChildText {
|
|
||||||
s, l := spaceDecompose(str)
|
|
||||||
return &filterChildText{s, l, text}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterChildText) apply(p *pather) {
|
|
||||||
for _, c := range p.candidates {
|
|
||||||
for _, cc := range c.Child {
|
|
||||||
if cc, ok := cc.(*Element); ok &&
|
|
||||||
spaceMatch(f.space, cc.Space) &&
|
|
||||||
f.tag == cc.Tag &&
|
|
||||||
f.text == cc.Text() {
|
|
||||||
p.scratch = append(p.scratch, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.candidates, p.scratch = p.scratch, p.candidates[0:0]
|
|
||||||
}
|
|
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
Normal file
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/AUTHORS.
|
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
28
vendor/github.com/golang/protobuf/LICENSE
generated
vendored
Normal file
28
vendor/github.com/golang/protobuf/LICENSE
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
530
vendor/github.com/golang/protobuf/jsonpb/decode.go
generated
vendored
Normal file
530
vendor/github.com/golang/protobuf/jsonpb/decode.go
generated
vendored
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
// Copyright 2015 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 jsonpb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrapJSONUnmarshalV2 = false
|
||||||
|
|
||||||
|
// UnmarshalNext unmarshals the next JSON object from d into m.
|
||||||
|
func UnmarshalNext(d *json.Decoder, m proto.Message) error {
|
||||||
|
return new(Unmarshaler).UnmarshalNext(d, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals a JSON object from r into m.
|
||||||
|
func Unmarshal(r io.Reader, m proto.Message) error {
|
||||||
|
return new(Unmarshaler).Unmarshal(r, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalString unmarshals a JSON object from s into m.
|
||||||
|
func UnmarshalString(s string, m proto.Message) error {
|
||||||
|
return new(Unmarshaler).Unmarshal(strings.NewReader(s), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshaler is a configurable object for converting from a JSON
|
||||||
|
// representation to a protocol buffer object.
|
||||||
|
type Unmarshaler struct {
|
||||||
|
// AllowUnknownFields specifies whether to allow messages to contain
|
||||||
|
// unknown JSON fields, as opposed to failing to unmarshal.
|
||||||
|
AllowUnknownFields bool
|
||||||
|
|
||||||
|
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
|
||||||
|
// If unset, the global registry is used by default.
|
||||||
|
AnyResolver AnyResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPBUnmarshaler is implemented by protobuf messages that customize the way
|
||||||
|
// they are unmarshaled from JSON. Messages that implement this should also
|
||||||
|
// implement JSONPBMarshaler so that the custom format can be produced.
|
||||||
|
//
|
||||||
|
// The JSON unmarshaling must follow the JSON to proto specification:
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||||
|
//
|
||||||
|
// Deprecated: Custom types should implement protobuf reflection instead.
|
||||||
|
type JSONPBUnmarshaler interface {
|
||||||
|
UnmarshalJSONPB(*Unmarshaler, []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals a JSON object from r into m.
|
||||||
|
func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error {
|
||||||
|
return u.UnmarshalNext(json.NewDecoder(r), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalNext unmarshals the next JSON object from d into m.
|
||||||
|
func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error {
|
||||||
|
if m == nil {
|
||||||
|
return errors.New("invalid nil message")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the next JSON object from the stream.
|
||||||
|
raw := json.RawMessage{}
|
||||||
|
if err := d.Decode(&raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for custom unmarshalers first since they may not properly
|
||||||
|
// implement protobuf reflection that the logic below relies on.
|
||||||
|
if jsu, ok := m.(JSONPBUnmarshaler); ok {
|
||||||
|
return jsu.UnmarshalJSONPB(u, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
mr := proto.MessageReflect(m)
|
||||||
|
|
||||||
|
// NOTE: For historical reasons, a top-level null is treated as a noop.
|
||||||
|
// This is incorrect, but kept for compatibility.
|
||||||
|
if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if wrapJSONUnmarshalV2 {
|
||||||
|
// NOTE: If input message is non-empty, we need to preserve merge semantics
|
||||||
|
// of the old jsonpb implementation. These semantics are not supported by
|
||||||
|
// the protobuf JSON specification.
|
||||||
|
isEmpty := true
|
||||||
|
mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
|
||||||
|
isEmpty = false // at least one iteration implies non-empty
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if !isEmpty {
|
||||||
|
// Perform unmarshaling into a newly allocated, empty message.
|
||||||
|
mr = mr.New()
|
||||||
|
|
||||||
|
// Use a defer to copy all unmarshaled fields into the original message.
|
||||||
|
dst := proto.MessageReflect(m)
|
||||||
|
defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||||
|
dst.Set(fd, v)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal using the v2 JSON unmarshaler.
|
||||||
|
opts := protojson.UnmarshalOptions{
|
||||||
|
DiscardUnknown: u.AllowUnknownFields,
|
||||||
|
}
|
||||||
|
if u.AnyResolver != nil {
|
||||||
|
opts.Resolver = anyResolver{u.AnyResolver}
|
||||||
|
}
|
||||||
|
return opts.Unmarshal(raw, mr.Interface())
|
||||||
|
} else {
|
||||||
|
if err := u.unmarshalMessage(mr, raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return protoV2.CheckInitialized(mr.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error {
|
||||||
|
md := m.Descriptor()
|
||||||
|
fds := md.Fields()
|
||||||
|
|
||||||
|
if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok {
|
||||||
|
return jsu.UnmarshalJSONPB(u, in)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch wellKnownType(md.FullName()) {
|
||||||
|
case "Any":
|
||||||
|
var jsonObject map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonObject); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawTypeURL, ok := jsonObject["@type"]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("Any JSON doesn't have '@type'")
|
||||||
|
}
|
||||||
|
typeURL, err := unquoteString(string(rawTypeURL))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL)
|
||||||
|
}
|
||||||
|
m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL))
|
||||||
|
|
||||||
|
var m2 protoreflect.Message
|
||||||
|
if u.AnyResolver != nil {
|
||||||
|
mi, err := u.AnyResolver.Resolve(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m2 = proto.MessageReflect(mi)
|
||||||
|
} else {
|
||||||
|
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
if err == protoregistry.NotFound {
|
||||||
|
return fmt.Errorf("could not resolve Any message type: %v", typeURL)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m2 = mt.New()
|
||||||
|
}
|
||||||
|
|
||||||
|
if wellKnownType(m2.Descriptor().FullName()) != "" {
|
||||||
|
rawValue, ok := jsonObject["value"]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("Any JSON doesn't have 'value'")
|
||||||
|
}
|
||||||
|
if err := u.unmarshalMessage(m2, rawValue); err != nil {
|
||||||
|
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delete(jsonObject, "@type")
|
||||||
|
rawJSON, err := json.Marshal(jsonObject)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
|
||||||
|
}
|
||||||
|
if err = u.unmarshalMessage(m2, rawJSON); err != nil {
|
||||||
|
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rawWire, err := protoV2.Marshal(m2.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err)
|
||||||
|
}
|
||||||
|
m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire))
|
||||||
|
return nil
|
||||||
|
case "BoolValue", "BytesValue", "StringValue",
|
||||||
|
"Int32Value", "UInt32Value", "FloatValue",
|
||||||
|
"Int64Value", "UInt64Value", "DoubleValue":
|
||||||
|
fd := fds.ByNumber(1)
|
||||||
|
v, err := u.unmarshalValue(m.NewField(fd), in, fd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
return nil
|
||||||
|
case "Duration":
|
||||||
|
v, err := unquoteString(string(in))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d, err := time.ParseDuration(v)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad Duration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sec := d.Nanoseconds() / 1e9
|
||||||
|
nsec := d.Nanoseconds() % 1e9
|
||||||
|
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
|
||||||
|
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
|
||||||
|
return nil
|
||||||
|
case "Timestamp":
|
||||||
|
v, err := unquoteString(string(in))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t, err := time.Parse(time.RFC3339Nano, v)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad Timestamp: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sec := t.Unix()
|
||||||
|
nsec := t.Nanosecond()
|
||||||
|
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
|
||||||
|
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
|
||||||
|
return nil
|
||||||
|
case "Value":
|
||||||
|
switch {
|
||||||
|
case string(in) == "null":
|
||||||
|
m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0))
|
||||||
|
case string(in) == "true":
|
||||||
|
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true))
|
||||||
|
case string(in) == "false":
|
||||||
|
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false))
|
||||||
|
case hasPrefixAndSuffix('"', in, '"'):
|
||||||
|
s, err := unquoteString(string(in))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unrecognized type for Value %q", in)
|
||||||
|
}
|
||||||
|
m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s))
|
||||||
|
case hasPrefixAndSuffix('[', in, ']'):
|
||||||
|
v := m.Mutable(fds.ByNumber(6))
|
||||||
|
return u.unmarshalMessage(v.Message(), in)
|
||||||
|
case hasPrefixAndSuffix('{', in, '}'):
|
||||||
|
v := m.Mutable(fds.ByNumber(5))
|
||||||
|
return u.unmarshalMessage(v.Message(), in)
|
||||||
|
default:
|
||||||
|
f, err := strconv.ParseFloat(string(in), 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unrecognized type for Value %q", in)
|
||||||
|
}
|
||||||
|
m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "ListValue":
|
||||||
|
var jsonArray []json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonArray); err != nil {
|
||||||
|
return fmt.Errorf("bad ListValue: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lv := m.Mutable(fds.ByNumber(1)).List()
|
||||||
|
for _, raw := range jsonArray {
|
||||||
|
ve := lv.NewElement()
|
||||||
|
if err := u.unmarshalMessage(ve.Message(), raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lv.Append(ve)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "Struct":
|
||||||
|
var jsonObject map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonObject); err != nil {
|
||||||
|
return fmt.Errorf("bad StructValue: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mv := m.Mutable(fds.ByNumber(1)).Map()
|
||||||
|
for key, raw := range jsonObject {
|
||||||
|
kv := protoreflect.ValueOf(key).MapKey()
|
||||||
|
vv := mv.NewValue()
|
||||||
|
if err := u.unmarshalMessage(vv.Message(), raw); err != nil {
|
||||||
|
return fmt.Errorf("bad value in StructValue for key %q: %v", key, err)
|
||||||
|
}
|
||||||
|
mv.Set(kv, vv)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonObject map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonObject); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle known fields.
|
||||||
|
for i := 0; i < fds.Len(); i++ {
|
||||||
|
fd := fds.Get(i)
|
||||||
|
if fd.IsWeak() && fd.Message().IsPlaceholder() {
|
||||||
|
continue // weak reference is not linked in
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for any raw JSON value associated with this field.
|
||||||
|
var raw json.RawMessage
|
||||||
|
name := string(fd.Name())
|
||||||
|
if fd.Kind() == protoreflect.GroupKind {
|
||||||
|
name = string(fd.Message().Name())
|
||||||
|
}
|
||||||
|
if v, ok := jsonObject[name]; ok {
|
||||||
|
delete(jsonObject, name)
|
||||||
|
raw = v
|
||||||
|
}
|
||||||
|
name = string(fd.JSONName())
|
||||||
|
if v, ok := jsonObject[name]; ok {
|
||||||
|
delete(jsonObject, name)
|
||||||
|
raw = v
|
||||||
|
}
|
||||||
|
|
||||||
|
field := m.NewField(fd)
|
||||||
|
// Unmarshal the field value.
|
||||||
|
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v, err := u.unmarshalValue(field, raw, fd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle extension fields.
|
||||||
|
for name, raw := range jsonObject {
|
||||||
|
if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the extension field by name.
|
||||||
|
xname := protoreflect.FullName(name[len("[") : len(name)-len("]")])
|
||||||
|
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
|
||||||
|
if xt == nil && isMessageSet(md) {
|
||||||
|
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
|
||||||
|
}
|
||||||
|
if xt == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(jsonObject, name)
|
||||||
|
fd := xt.TypeDescriptor()
|
||||||
|
if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
|
||||||
|
return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName())
|
||||||
|
}
|
||||||
|
|
||||||
|
field := m.NewField(fd)
|
||||||
|
// Unmarshal the field value.
|
||||||
|
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v, err := u.unmarshalValue(field, raw, fd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !u.AllowUnknownFields && len(jsonObject) > 0 {
|
||||||
|
for name := range jsonObject {
|
||||||
|
return fmt.Errorf("unknown field %q in %v", name, md.FullName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
|
||||||
|
if fd.Cardinality() == protoreflect.Repeated {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if md := fd.Message(); md != nil {
|
||||||
|
return md.FullName() == "google.protobuf.Value"
|
||||||
|
}
|
||||||
|
if ed := fd.Enum(); ed != nil {
|
||||||
|
return ed.FullName() == "google.protobuf.NullValue"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool {
|
||||||
|
if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated {
|
||||||
|
_, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||||
|
switch {
|
||||||
|
case fd.IsList():
|
||||||
|
var jsonArray []json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonArray); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
lv := v.List()
|
||||||
|
for _, raw := range jsonArray {
|
||||||
|
ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd)
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
lv.Append(ve)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
case fd.IsMap():
|
||||||
|
var jsonObject map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(in, &jsonObject); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
kfd := fd.MapKey()
|
||||||
|
vfd := fd.MapValue()
|
||||||
|
mv := v.Map()
|
||||||
|
for key, raw := range jsonObject {
|
||||||
|
var kv protoreflect.MapKey
|
||||||
|
if kfd.Kind() == protoreflect.StringKind {
|
||||||
|
kv = protoreflect.ValueOf(key).MapKey()
|
||||||
|
} else {
|
||||||
|
v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd)
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
kv = v.MapKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd)
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
mv.Set(kv, vv)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
default:
|
||||||
|
return u.unmarshalSingularValue(v, in, fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nonFinite = map[string]float64{
|
||||||
|
`"NaN"`: math.NaN(),
|
||||||
|
`"Infinity"`: math.Inf(+1),
|
||||||
|
`"-Infinity"`: math.Inf(-1),
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||||
|
switch fd.Kind() {
|
||||||
|
case protoreflect.BoolKind:
|
||||||
|
return unmarshalValue(in, new(bool))
|
||||||
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
||||||
|
return unmarshalValue(trimQuote(in), new(int32))
|
||||||
|
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||||
|
return unmarshalValue(trimQuote(in), new(int64))
|
||||||
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
||||||
|
return unmarshalValue(trimQuote(in), new(uint32))
|
||||||
|
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||||
|
return unmarshalValue(trimQuote(in), new(uint64))
|
||||||
|
case protoreflect.FloatKind:
|
||||||
|
if f, ok := nonFinite[string(in)]; ok {
|
||||||
|
return protoreflect.ValueOfFloat32(float32(f)), nil
|
||||||
|
}
|
||||||
|
return unmarshalValue(trimQuote(in), new(float32))
|
||||||
|
case protoreflect.DoubleKind:
|
||||||
|
if f, ok := nonFinite[string(in)]; ok {
|
||||||
|
return protoreflect.ValueOfFloat64(float64(f)), nil
|
||||||
|
}
|
||||||
|
return unmarshalValue(trimQuote(in), new(float64))
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
return unmarshalValue(in, new(string))
|
||||||
|
case protoreflect.BytesKind:
|
||||||
|
return unmarshalValue(in, new([]byte))
|
||||||
|
case protoreflect.EnumKind:
|
||||||
|
if hasPrefixAndSuffix('"', in, '"') {
|
||||||
|
vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in)))
|
||||||
|
if vd == nil {
|
||||||
|
return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName())
|
||||||
|
}
|
||||||
|
return protoreflect.ValueOfEnum(vd.Number()), nil
|
||||||
|
}
|
||||||
|
return unmarshalValue(in, new(protoreflect.EnumNumber))
|
||||||
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
|
err := u.unmarshalMessage(v.Message(), in)
|
||||||
|
return v, err
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) {
|
||||||
|
err := json.Unmarshal(in, v)
|
||||||
|
return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func unquoteString(in string) (out string, err error) {
|
||||||
|
err = json.Unmarshal([]byte(in), &out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool {
|
||||||
|
if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// trimQuote is like unquoteString but simply strips surrounding quotes.
|
||||||
|
// This is incorrect, but is behavior done by the legacy implementation.
|
||||||
|
func trimQuote(in []byte) []byte {
|
||||||
|
if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' {
|
||||||
|
in = in[1 : len(in)-1]
|
||||||
|
}
|
||||||
|
return in
|
||||||
|
}
|
559
vendor/github.com/golang/protobuf/jsonpb/encode.go
generated
vendored
Normal file
559
vendor/github.com/golang/protobuf/jsonpb/encode.go
generated
vendored
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
// Copyright 2015 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 jsonpb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrapJSONMarshalV2 = false
|
||||||
|
|
||||||
|
// Marshaler is a configurable object for marshaling protocol buffer messages
|
||||||
|
// to the specified JSON representation.
|
||||||
|
type Marshaler struct {
|
||||||
|
// OrigName specifies whether to use the original protobuf name for fields.
|
||||||
|
OrigName bool
|
||||||
|
|
||||||
|
// EnumsAsInts specifies whether to render enum values as integers,
|
||||||
|
// as opposed to string values.
|
||||||
|
EnumsAsInts bool
|
||||||
|
|
||||||
|
// EmitDefaults specifies whether to render fields with zero values.
|
||||||
|
EmitDefaults bool
|
||||||
|
|
||||||
|
// Indent controls whether the output is compact or not.
|
||||||
|
// If empty, the output is compact JSON. Otherwise, every JSON object
|
||||||
|
// entry and JSON array value will be on its own line.
|
||||||
|
// Each line will be preceded by repeated copies of Indent, where the
|
||||||
|
// number of copies is the current indentation depth.
|
||||||
|
Indent string
|
||||||
|
|
||||||
|
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
|
||||||
|
// If unset, the global registry is used by default.
|
||||||
|
AnyResolver AnyResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPBMarshaler is implemented by protobuf messages that customize the
|
||||||
|
// way they are marshaled to JSON. Messages that implement this should also
|
||||||
|
// implement JSONPBUnmarshaler so that the custom format can be parsed.
|
||||||
|
//
|
||||||
|
// The JSON marshaling must follow the proto to JSON specification:
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||||
|
//
|
||||||
|
// Deprecated: Custom types should implement protobuf reflection instead.
|
||||||
|
type JSONPBMarshaler interface {
|
||||||
|
MarshalJSONPB(*Marshaler) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal serializes a protobuf message as JSON into w.
|
||||||
|
func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
|
||||||
|
b, err := jm.marshal(m)
|
||||||
|
if len(b) > 0 {
|
||||||
|
if _, err := w.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalToString serializes a protobuf message as JSON in string form.
|
||||||
|
func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
|
||||||
|
b, err := jm.marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
|
||||||
|
v := reflect.ValueOf(m)
|
||||||
|
if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
||||||
|
return nil, errors.New("Marshal called with nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for custom marshalers first since they may not properly
|
||||||
|
// implement protobuf reflection that the logic below relies on.
|
||||||
|
if jsm, ok := m.(JSONPBMarshaler); ok {
|
||||||
|
return jsm.MarshalJSONPB(jm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if wrapJSONMarshalV2 {
|
||||||
|
opts := protojson.MarshalOptions{
|
||||||
|
UseProtoNames: jm.OrigName,
|
||||||
|
UseEnumNumbers: jm.EnumsAsInts,
|
||||||
|
EmitUnpopulated: jm.EmitDefaults,
|
||||||
|
Indent: jm.Indent,
|
||||||
|
}
|
||||||
|
if jm.AnyResolver != nil {
|
||||||
|
opts.Resolver = anyResolver{jm.AnyResolver}
|
||||||
|
}
|
||||||
|
return opts.Marshal(proto.MessageReflect(m).Interface())
|
||||||
|
} else {
|
||||||
|
// Check for unpopulated required fields first.
|
||||||
|
m2 := proto.MessageReflect(m)
|
||||||
|
if err := protoV2.CheckInitialized(m2.Interface()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w := jsonWriter{Marshaler: jm}
|
||||||
|
err := w.marshalMessage(m2, "", "")
|
||||||
|
return w.buf, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonWriter struct {
|
||||||
|
*Marshaler
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) write(s string) {
|
||||||
|
w.buf = append(w.buf, s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
|
||||||
|
if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok {
|
||||||
|
b, err := jsm.MarshalJSONPB(w.Marshaler)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if typeURL != "" {
|
||||||
|
// we are marshaling this object to an Any type
|
||||||
|
var js map[string]*json.RawMessage
|
||||||
|
if err = json.Unmarshal(b, &js); err != nil {
|
||||||
|
return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
|
||||||
|
}
|
||||||
|
turl, err := json.Marshal(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
|
||||||
|
}
|
||||||
|
js["@type"] = (*json.RawMessage)(&turl)
|
||||||
|
if b, err = json.Marshal(js); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.write(string(b))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
md := m.Descriptor()
|
||||||
|
fds := md.Fields()
|
||||||
|
|
||||||
|
// Handle well-known types.
|
||||||
|
const secondInNanos = int64(time.Second / time.Nanosecond)
|
||||||
|
switch wellKnownType(md.FullName()) {
|
||||||
|
case "Any":
|
||||||
|
return w.marshalAny(m, indent)
|
||||||
|
case "BoolValue", "BytesValue", "StringValue",
|
||||||
|
"Int32Value", "UInt32Value", "FloatValue",
|
||||||
|
"Int64Value", "UInt64Value", "DoubleValue":
|
||||||
|
fd := fds.ByNumber(1)
|
||||||
|
return w.marshalValue(fd, m.Get(fd), indent)
|
||||||
|
case "Duration":
|
||||||
|
const maxSecondsInDuration = 315576000000
|
||||||
|
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
|
||||||
|
// depending on required precision."
|
||||||
|
s := m.Get(fds.ByNumber(1)).Int()
|
||||||
|
ns := m.Get(fds.ByNumber(2)).Int()
|
||||||
|
if s < -maxSecondsInDuration || s > maxSecondsInDuration {
|
||||||
|
return fmt.Errorf("seconds out of range %v", s)
|
||||||
|
}
|
||||||
|
if ns <= -secondInNanos || ns >= secondInNanos {
|
||||||
|
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
|
||||||
|
}
|
||||||
|
if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
|
||||||
|
return errors.New("signs of seconds and nanos do not match")
|
||||||
|
}
|
||||||
|
var sign string
|
||||||
|
if s < 0 || ns < 0 {
|
||||||
|
sign, s, ns = "-", -1*s, -1*ns
|
||||||
|
}
|
||||||
|
x := fmt.Sprintf("%s%d.%09d", sign, s, ns)
|
||||||
|
x = strings.TrimSuffix(x, "000")
|
||||||
|
x = strings.TrimSuffix(x, "000")
|
||||||
|
x = strings.TrimSuffix(x, ".000")
|
||||||
|
w.write(fmt.Sprintf(`"%vs"`, x))
|
||||||
|
return nil
|
||||||
|
case "Timestamp":
|
||||||
|
// "RFC 3339, where generated output will always be Z-normalized
|
||||||
|
// and uses 0, 3, 6 or 9 fractional digits."
|
||||||
|
s := m.Get(fds.ByNumber(1)).Int()
|
||||||
|
ns := m.Get(fds.ByNumber(2)).Int()
|
||||||
|
if ns < 0 || ns >= secondInNanos {
|
||||||
|
return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
|
||||||
|
}
|
||||||
|
t := time.Unix(s, ns).UTC()
|
||||||
|
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
|
||||||
|
x := t.Format("2006-01-02T15:04:05.000000000")
|
||||||
|
x = strings.TrimSuffix(x, "000")
|
||||||
|
x = strings.TrimSuffix(x, "000")
|
||||||
|
x = strings.TrimSuffix(x, ".000")
|
||||||
|
w.write(fmt.Sprintf(`"%vZ"`, x))
|
||||||
|
return nil
|
||||||
|
case "Value":
|
||||||
|
// JSON value; which is a null, number, string, bool, object, or array.
|
||||||
|
od := md.Oneofs().Get(0)
|
||||||
|
fd := m.WhichOneof(od)
|
||||||
|
if fd == nil {
|
||||||
|
return errors.New("nil Value")
|
||||||
|
}
|
||||||
|
return w.marshalValue(fd, m.Get(fd), indent)
|
||||||
|
case "Struct", "ListValue":
|
||||||
|
// JSON object or array.
|
||||||
|
fd := fds.ByNumber(1)
|
||||||
|
return w.marshalValue(fd, m.Get(fd), indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write("{")
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
firstField := true
|
||||||
|
if typeURL != "" {
|
||||||
|
if err := w.marshalTypeURL(indent, typeURL); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
firstField = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < fds.Len(); {
|
||||||
|
fd := fds.Get(i)
|
||||||
|
if od := fd.ContainingOneof(); od != nil {
|
||||||
|
fd = m.WhichOneof(od)
|
||||||
|
i += od.Fields().Len()
|
||||||
|
if fd == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
v := m.Get(fd)
|
||||||
|
|
||||||
|
if !m.Has(fd) {
|
||||||
|
if !w.EmitDefaults || fd.ContainingOneof() != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
|
||||||
|
v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !firstField {
|
||||||
|
w.writeComma()
|
||||||
|
}
|
||||||
|
if err := w.marshalField(fd, v, indent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
firstField = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle proto2 extensions.
|
||||||
|
if md.ExtensionRanges().Len() > 0 {
|
||||||
|
// Collect a sorted list of all extension descriptor and values.
|
||||||
|
type ext struct {
|
||||||
|
desc protoreflect.FieldDescriptor
|
||||||
|
val protoreflect.Value
|
||||||
|
}
|
||||||
|
var exts []ext
|
||||||
|
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||||
|
if fd.IsExtension() {
|
||||||
|
exts = append(exts, ext{fd, v})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Slice(exts, func(i, j int) bool {
|
||||||
|
return exts[i].desc.Number() < exts[j].desc.Number()
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, ext := range exts {
|
||||||
|
if !firstField {
|
||||||
|
w.writeComma()
|
||||||
|
}
|
||||||
|
if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
firstField = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
}
|
||||||
|
w.write("}")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) writeComma() {
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(",\n")
|
||||||
|
} else {
|
||||||
|
w.write(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
|
||||||
|
// "If the Any contains a value that has a special JSON mapping,
|
||||||
|
// it will be converted as follows: {"@type": xxx, "value": yyy}.
|
||||||
|
// Otherwise, the value will be converted into a JSON object,
|
||||||
|
// and the "@type" field will be inserted to indicate the actual data type."
|
||||||
|
md := m.Descriptor()
|
||||||
|
typeURL := m.Get(md.Fields().ByNumber(1)).String()
|
||||||
|
rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
|
||||||
|
|
||||||
|
var m2 protoreflect.Message
|
||||||
|
if w.AnyResolver != nil {
|
||||||
|
mi, err := w.AnyResolver.Resolve(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m2 = proto.MessageReflect(mi)
|
||||||
|
} else {
|
||||||
|
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m2 = mt.New()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if wellKnownType(m2.Descriptor().FullName()) == "" {
|
||||||
|
return w.marshalMessage(m2, indent, typeURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write("{")
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
}
|
||||||
|
if err := w.marshalTypeURL(indent, typeURL); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.writeComma()
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
w.write(`"value": `)
|
||||||
|
} else {
|
||||||
|
w.write(`"value":`)
|
||||||
|
}
|
||||||
|
if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
}
|
||||||
|
w.write("}")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
w.write(`"@type":`)
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(" ")
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(typeURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.write(string(b))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// marshalField writes field description and value to the Writer.
|
||||||
|
func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
w.write(`"`)
|
||||||
|
switch {
|
||||||
|
case fd.IsExtension():
|
||||||
|
// For message set, use the fname of the message as the extension name.
|
||||||
|
name := string(fd.FullName())
|
||||||
|
if isMessageSet(fd.ContainingMessage()) {
|
||||||
|
name = strings.TrimSuffix(name, ".message_set_extension")
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write("[" + name + "]")
|
||||||
|
case w.OrigName:
|
||||||
|
name := string(fd.Name())
|
||||||
|
if fd.Kind() == protoreflect.GroupKind {
|
||||||
|
name = string(fd.Message().Name())
|
||||||
|
}
|
||||||
|
w.write(name)
|
||||||
|
default:
|
||||||
|
w.write(string(fd.JSONName()))
|
||||||
|
}
|
||||||
|
w.write(`":`)
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(" ")
|
||||||
|
}
|
||||||
|
return w.marshalValue(fd, v, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
|
||||||
|
switch {
|
||||||
|
case fd.IsList():
|
||||||
|
w.write("[")
|
||||||
|
comma := ""
|
||||||
|
lv := v.List()
|
||||||
|
for i := 0; i < lv.Len(); i++ {
|
||||||
|
w.write(comma)
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
comma = ","
|
||||||
|
}
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
w.write("]")
|
||||||
|
return nil
|
||||||
|
case fd.IsMap():
|
||||||
|
kfd := fd.MapKey()
|
||||||
|
vfd := fd.MapValue()
|
||||||
|
mv := v.Map()
|
||||||
|
|
||||||
|
// Collect a sorted list of all map keys and values.
|
||||||
|
type entry struct{ key, val protoreflect.Value }
|
||||||
|
var entries []entry
|
||||||
|
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
|
||||||
|
entries = append(entries, entry{k.Value(), v})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Slice(entries, func(i, j int) bool {
|
||||||
|
switch kfd.Kind() {
|
||||||
|
case protoreflect.BoolKind:
|
||||||
|
return !entries[i].key.Bool() && entries[j].key.Bool()
|
||||||
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||||
|
return entries[i].key.Int() < entries[j].key.Int()
|
||||||
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||||
|
return entries[i].key.Uint() < entries[j].key.Uint()
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
return entries[i].key.String() < entries[j].key.String()
|
||||||
|
default:
|
||||||
|
panic("invalid kind")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
w.write(`{`)
|
||||||
|
comma := ""
|
||||||
|
for _, entry := range entries {
|
||||||
|
w.write(comma)
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := fmt.Sprint(entry.key.Interface())
|
||||||
|
b, err := json.Marshal(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.write(string(b))
|
||||||
|
|
||||||
|
w.write(`:`)
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write(` `)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
comma = ","
|
||||||
|
}
|
||||||
|
if w.Indent != "" {
|
||||||
|
w.write("\n")
|
||||||
|
w.write(indent)
|
||||||
|
w.write(w.Indent)
|
||||||
|
}
|
||||||
|
w.write(`}`)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return w.marshalSingularValue(fd, v, indent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
|
||||||
|
switch {
|
||||||
|
case !v.IsValid():
|
||||||
|
w.write("null")
|
||||||
|
return nil
|
||||||
|
case fd.Message() != nil:
|
||||||
|
return w.marshalMessage(v.Message(), indent+w.Indent, "")
|
||||||
|
case fd.Enum() != nil:
|
||||||
|
if fd.Enum().FullName() == "google.protobuf.NullValue" {
|
||||||
|
w.write("null")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vd := fd.Enum().Values().ByNumber(v.Enum())
|
||||||
|
if vd == nil || w.EnumsAsInts {
|
||||||
|
w.write(strconv.Itoa(int(v.Enum())))
|
||||||
|
} else {
|
||||||
|
w.write(`"` + string(vd.Name()) + `"`)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
switch v.Interface().(type) {
|
||||||
|
case float32, float64:
|
||||||
|
switch {
|
||||||
|
case math.IsInf(v.Float(), +1):
|
||||||
|
w.write(`"Infinity"`)
|
||||||
|
return nil
|
||||||
|
case math.IsInf(v.Float(), -1):
|
||||||
|
w.write(`"-Infinity"`)
|
||||||
|
return nil
|
||||||
|
case math.IsNaN(v.Float()):
|
||||||
|
w.write(`"NaN"`)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case int64, uint64:
|
||||||
|
w.write(fmt.Sprintf(`"%d"`, v.Interface()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(v.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.write(string(b))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
69
vendor/github.com/golang/protobuf/jsonpb/json.go
generated
vendored
Normal file
69
vendor/github.com/golang/protobuf/jsonpb/json.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2015 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 jsonpb provides functionality to marshal and unmarshal between a
|
||||||
|
// protocol buffer message and JSON. It follows the specification at
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto3#json.
|
||||||
|
//
|
||||||
|
// Do not rely on the default behavior of the standard encoding/json package
|
||||||
|
// when called on generated message types as it does not operate correctly.
|
||||||
|
//
|
||||||
|
// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson"
|
||||||
|
// package instead.
|
||||||
|
package jsonpb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AnyResolver takes a type URL, present in an Any message,
|
||||||
|
// and resolves it into an instance of the associated message.
|
||||||
|
type AnyResolver interface {
|
||||||
|
Resolve(typeURL string) (proto.Message, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type anyResolver struct{ AnyResolver }
|
||||||
|
|
||||||
|
func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
|
||||||
|
return r.FindMessageByURL(string(message))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) {
|
||||||
|
m, err := r.Resolve(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return protoimpl.X.MessageTypeOf(m), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
|
||||||
|
return protoregistry.GlobalTypes.FindExtensionByName(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
|
||||||
|
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func wellKnownType(s protoreflect.FullName) string {
|
||||||
|
if s.Parent() == "google.protobuf" {
|
||||||
|
switch s.Name() {
|
||||||
|
case "Empty", "Any",
|
||||||
|
"BoolValue", "BytesValue", "StringValue",
|
||||||
|
"Int32Value", "UInt32Value", "FloatValue",
|
||||||
|
"Int64Value", "UInt64Value", "DoubleValue",
|
||||||
|
"Duration", "Timestamp",
|
||||||
|
"NullValue", "Struct", "Value", "ListValue":
|
||||||
|
return string(s.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMessageSet(md protoreflect.MessageDescriptor) bool {
|
||||||
|
ms, ok := md.(interface{ IsMessageSet() bool })
|
||||||
|
return ok && ms.IsMessageSet()
|
||||||
|
}
|
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
Normal file
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WireVarint = 0
|
||||||
|
WireFixed32 = 5
|
||||||
|
WireFixed64 = 1
|
||||||
|
WireBytes = 2
|
||||||
|
WireStartGroup = 3
|
||||||
|
WireEndGroup = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// EncodeVarint returns the varint encoded bytes of v.
|
||||||
|
func EncodeVarint(v uint64) []byte {
|
||||||
|
return protowire.AppendVarint(nil, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SizeVarint returns the length of the varint encoded bytes of v.
|
||||||
|
// This is equal to len(EncodeVarint(v)).
|
||||||
|
func SizeVarint(v uint64) int {
|
||||||
|
return protowire.SizeVarint(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeVarint parses a varint encoded integer from b,
|
||||||
|
// returning the integer value and the length of the varint.
|
||||||
|
// It returns (0, 0) if there is a parse error.
|
||||||
|
func DecodeVarint(b []byte) (uint64, int) {
|
||||||
|
v, n := protowire.ConsumeVarint(b)
|
||||||
|
if n < 0 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
return v, n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer is a buffer for encoding and decoding the protobuf wire format.
|
||||||
|
// It may be reused between invocations to reduce memory usage.
|
||||||
|
type Buffer struct {
|
||||||
|
buf []byte
|
||||||
|
idx int
|
||||||
|
deterministic bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBuffer allocates a new Buffer initialized with buf,
|
||||||
|
// where the contents of buf are considered the unread portion of the buffer.
|
||||||
|
func NewBuffer(buf []byte) *Buffer {
|
||||||
|
return &Buffer{buf: buf}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeterministic specifies whether to use deterministic serialization.
|
||||||
|
//
|
||||||
|
// Deterministic serialization guarantees that for a given binary, equal
|
||||||
|
// messages will always be serialized to the same bytes. This implies:
|
||||||
|
//
|
||||||
|
// - Repeated serialization of a message will return the same bytes.
|
||||||
|
// - Different processes of the same binary (which may be executing on
|
||||||
|
// different machines) will serialize equal messages to the same bytes.
|
||||||
|
//
|
||||||
|
// Note that the deterministic serialization is NOT canonical across
|
||||||
|
// languages. It is not guaranteed to remain stable over time. It is unstable
|
||||||
|
// across different builds with schema changes due to unknown fields.
|
||||||
|
// Users who need canonical serialization (e.g., persistent storage in a
|
||||||
|
// canonical form, fingerprinting, etc.) should define their own
|
||||||
|
// canonicalization specification and implement their own serializer rather
|
||||||
|
// than relying on this API.
|
||||||
|
//
|
||||||
|
// If deterministic serialization is requested, map entries will be sorted
|
||||||
|
// by keys in lexographical order. This is an implementation detail and
|
||||||
|
// subject to change.
|
||||||
|
func (b *Buffer) SetDeterministic(deterministic bool) {
|
||||||
|
b.deterministic = deterministic
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBuf sets buf as the internal buffer,
|
||||||
|
// where the contents of buf are considered the unread portion of the buffer.
|
||||||
|
func (b *Buffer) SetBuf(buf []byte) {
|
||||||
|
b.buf = buf
|
||||||
|
b.idx = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset clears the internal buffer of all written and unread data.
|
||||||
|
func (b *Buffer) Reset() {
|
||||||
|
b.buf = b.buf[:0]
|
||||||
|
b.idx = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the internal buffer.
|
||||||
|
func (b *Buffer) Bytes() []byte {
|
||||||
|
return b.buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unread returns the unread portion of the buffer.
|
||||||
|
func (b *Buffer) Unread() []byte {
|
||||||
|
return b.buf[b.idx:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal appends the wire-format encoding of m to the buffer.
|
||||||
|
func (b *Buffer) Marshal(m Message) error {
|
||||||
|
var err error
|
||||||
|
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal parses the wire-format message in the buffer and
|
||||||
|
// places the decoded results in m.
|
||||||
|
// It does not reset m before unmarshaling.
|
||||||
|
func (b *Buffer) Unmarshal(m Message) error {
|
||||||
|
err := UnmarshalMerge(b.Unread(), m)
|
||||||
|
b.idx = len(b.buf)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type unknownFields struct{ XXX_unrecognized protoimpl.UnknownFields }
|
||||||
|
|
||||||
|
func (m *unknownFields) String() string { panic("not implemented") }
|
||||||
|
func (m *unknownFields) Reset() { panic("not implemented") }
|
||||||
|
func (m *unknownFields) ProtoMessage() { panic("not implemented") }
|
||||||
|
|
||||||
|
// DebugPrint dumps the encoded bytes of b with a header and footer including s
|
||||||
|
// to stdout. This is only intended for debugging.
|
||||||
|
func (*Buffer) DebugPrint(s string, b []byte) {
|
||||||
|
m := MessageReflect(new(unknownFields))
|
||||||
|
m.SetUnknown(b)
|
||||||
|
b, _ = prototext.MarshalOptions{AllowPartial: true, Indent: "\t"}.Marshal(m.Interface())
|
||||||
|
fmt.Printf("==== %s ====\n%s==== %s ====\n", s, b, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeVarint appends an unsigned varint encoding to the buffer.
|
||||||
|
func (b *Buffer) EncodeVarint(v uint64) error {
|
||||||
|
b.buf = protowire.AppendVarint(b.buf, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeZigzag32 appends a 32-bit zig-zag varint encoding to the buffer.
|
||||||
|
func (b *Buffer) EncodeZigzag32(v uint64) error {
|
||||||
|
return b.EncodeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeZigzag64 appends a 64-bit zig-zag varint encoding to the buffer.
|
||||||
|
func (b *Buffer) EncodeZigzag64(v uint64) error {
|
||||||
|
return b.EncodeVarint(uint64((uint64(v) << 1) ^ uint64((int64(v) >> 63))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeFixed32 appends a 32-bit little-endian integer to the buffer.
|
||||||
|
func (b *Buffer) EncodeFixed32(v uint64) error {
|
||||||
|
b.buf = protowire.AppendFixed32(b.buf, uint32(v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeFixed64 appends a 64-bit little-endian integer to the buffer.
|
||||||
|
func (b *Buffer) EncodeFixed64(v uint64) error {
|
||||||
|
b.buf = protowire.AppendFixed64(b.buf, uint64(v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRawBytes appends a length-prefixed raw bytes to the buffer.
|
||||||
|
func (b *Buffer) EncodeRawBytes(v []byte) error {
|
||||||
|
b.buf = protowire.AppendBytes(b.buf, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeStringBytes appends a length-prefixed raw bytes to the buffer.
|
||||||
|
// It does not validate whether v contains valid UTF-8.
|
||||||
|
func (b *Buffer) EncodeStringBytes(v string) error {
|
||||||
|
b.buf = protowire.AppendString(b.buf, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeMessage appends a length-prefixed encoded message to the buffer.
|
||||||
|
func (b *Buffer) EncodeMessage(m Message) error {
|
||||||
|
var err error
|
||||||
|
b.buf = protowire.AppendVarint(b.buf, uint64(Size(m)))
|
||||||
|
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeVarint consumes an encoded unsigned varint from the buffer.
|
||||||
|
func (b *Buffer) DecodeVarint() (uint64, error) {
|
||||||
|
v, n := protowire.ConsumeVarint(b.buf[b.idx:])
|
||||||
|
if n < 0 {
|
||||||
|
return 0, protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
return uint64(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeZigzag32 consumes an encoded 32-bit zig-zag varint from the buffer.
|
||||||
|
func (b *Buffer) DecodeZigzag32() (uint64, error) {
|
||||||
|
v, err := b.DecodeVarint()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return uint64((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeZigzag64 consumes an encoded 64-bit zig-zag varint from the buffer.
|
||||||
|
func (b *Buffer) DecodeZigzag64() (uint64, error) {
|
||||||
|
v, err := b.DecodeVarint()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return uint64((uint64(v) >> 1) ^ uint64((int64(v&1)<<63)>>63)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeFixed32 consumes a 32-bit little-endian integer from the buffer.
|
||||||
|
func (b *Buffer) DecodeFixed32() (uint64, error) {
|
||||||
|
v, n := protowire.ConsumeFixed32(b.buf[b.idx:])
|
||||||
|
if n < 0 {
|
||||||
|
return 0, protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
return uint64(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeFixed64 consumes a 64-bit little-endian integer from the buffer.
|
||||||
|
func (b *Buffer) DecodeFixed64() (uint64, error) {
|
||||||
|
v, n := protowire.ConsumeFixed64(b.buf[b.idx:])
|
||||||
|
if n < 0 {
|
||||||
|
return 0, protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
return uint64(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRawBytes consumes a length-prefixed raw bytes from the buffer.
|
||||||
|
// If alloc is specified, it returns a copy the raw bytes
|
||||||
|
// rather than a sub-slice of the buffer.
|
||||||
|
func (b *Buffer) DecodeRawBytes(alloc bool) ([]byte, error) {
|
||||||
|
v, n := protowire.ConsumeBytes(b.buf[b.idx:])
|
||||||
|
if n < 0 {
|
||||||
|
return nil, protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
if alloc {
|
||||||
|
v = append([]byte(nil), v...)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeStringBytes consumes a length-prefixed raw bytes from the buffer.
|
||||||
|
// It does not validate whether the raw bytes contain valid UTF-8.
|
||||||
|
func (b *Buffer) DecodeStringBytes() (string, error) {
|
||||||
|
v, n := protowire.ConsumeString(b.buf[b.idx:])
|
||||||
|
if n < 0 {
|
||||||
|
return "", protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMessage consumes a length-prefixed message from the buffer.
|
||||||
|
// It does not reset m before unmarshaling.
|
||||||
|
func (b *Buffer) DecodeMessage(m Message) error {
|
||||||
|
v, err := b.DecodeRawBytes(false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return UnmarshalMerge(v, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeGroup consumes a message group from the buffer.
|
||||||
|
// It assumes that the start group marker has already been consumed and
|
||||||
|
// consumes all bytes until (and including the end group marker).
|
||||||
|
// It does not reset m before unmarshaling.
|
||||||
|
func (b *Buffer) DecodeGroup(m Message) error {
|
||||||
|
v, n, err := consumeGroup(b.buf[b.idx:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.idx += n
|
||||||
|
return UnmarshalMerge(v, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// consumeGroup parses b until it finds an end group marker, returning
|
||||||
|
// the raw bytes of the message (excluding the end group marker) and the
|
||||||
|
// the total length of the message (including the end group marker).
|
||||||
|
func consumeGroup(b []byte) ([]byte, int, error) {
|
||||||
|
b0 := b
|
||||||
|
depth := 1 // assume this follows a start group marker
|
||||||
|
for {
|
||||||
|
_, wtyp, tagLen := protowire.ConsumeTag(b)
|
||||||
|
if tagLen < 0 {
|
||||||
|
return nil, 0, protowire.ParseError(tagLen)
|
||||||
|
}
|
||||||
|
b = b[tagLen:]
|
||||||
|
|
||||||
|
var valLen int
|
||||||
|
switch wtyp {
|
||||||
|
case protowire.VarintType:
|
||||||
|
_, valLen = protowire.ConsumeVarint(b)
|
||||||
|
case protowire.Fixed32Type:
|
||||||
|
_, valLen = protowire.ConsumeFixed32(b)
|
||||||
|
case protowire.Fixed64Type:
|
||||||
|
_, valLen = protowire.ConsumeFixed64(b)
|
||||||
|
case protowire.BytesType:
|
||||||
|
_, valLen = protowire.ConsumeBytes(b)
|
||||||
|
case protowire.StartGroupType:
|
||||||
|
depth++
|
||||||
|
case protowire.EndGroupType:
|
||||||
|
depth--
|
||||||
|
default:
|
||||||
|
return nil, 0, errors.New("proto: cannot parse reserved wire type")
|
||||||
|
}
|
||||||
|
if valLen < 0 {
|
||||||
|
return nil, 0, protowire.ParseError(valLen)
|
||||||
|
}
|
||||||
|
b = b[valLen:]
|
||||||
|
|
||||||
|
if depth == 0 {
|
||||||
|
return b0[:len(b0)-len(b)-tagLen], len(b0) - len(b), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
Normal file
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetDefaults sets unpopulated scalar fields to their default values.
|
||||||
|
// Fields within a oneof are not set even if they have a default value.
|
||||||
|
// SetDefaults is recursively called upon any populated message fields.
|
||||||
|
func SetDefaults(m Message) {
|
||||||
|
if m != nil {
|
||||||
|
setDefaults(MessageReflect(m))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setDefaults(m protoreflect.Message) {
|
||||||
|
fds := m.Descriptor().Fields()
|
||||||
|
for i := 0; i < fds.Len(); i++ {
|
||||||
|
fd := fds.Get(i)
|
||||||
|
if !m.Has(fd) {
|
||||||
|
if fd.HasDefault() && fd.ContainingOneof() == nil {
|
||||||
|
v := fd.Default()
|
||||||
|
if fd.Kind() == protoreflect.BytesKind {
|
||||||
|
v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||||
|
switch {
|
||||||
|
// Handle singular message.
|
||||||
|
case fd.Cardinality() != protoreflect.Repeated:
|
||||||
|
if fd.Message() != nil {
|
||||||
|
setDefaults(m.Get(fd).Message())
|
||||||
|
}
|
||||||
|
// Handle list of messages.
|
||||||
|
case fd.IsList():
|
||||||
|
if fd.Message() != nil {
|
||||||
|
ls := m.Get(fd).List()
|
||||||
|
for i := 0; i < ls.Len(); i++ {
|
||||||
|
setDefaults(ls.Get(i).Message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle map of messages.
|
||||||
|
case fd.IsMap():
|
||||||
|
if fd.MapValue().Message() != nil {
|
||||||
|
ms := m.Get(fd).Map()
|
||||||
|
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||||
|
setDefaults(v.Message())
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
Normal file
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Deprecated: No longer returned.
|
||||||
|
ErrNil = errors.New("proto: Marshal called with nil")
|
||||||
|
|
||||||
|
// Deprecated: No longer returned.
|
||||||
|
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
||||||
|
|
||||||
|
// Deprecated: No longer returned.
|
||||||
|
ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func GetStats() Stats { return Stats{} }
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func MarshalMessageSet(interface{}) ([]byte, error) {
|
||||||
|
return nil, errors.New("proto: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func UnmarshalMessageSet([]byte, interface{}) error {
|
||||||
|
return errors.New("proto: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
|
||||||
|
return nil, errors.New("proto: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func UnmarshalMessageSetJSON([]byte, interface{}) error {
|
||||||
|
return errors.New("proto: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func RegisterMessageSetType(Message, int32, string) {}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func EnumName(m map[int32]string, v int32) string {
|
||||||
|
s, ok := m[v]
|
||||||
|
if ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return strconv.Itoa(int(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
|
||||||
|
if data[0] == '"' {
|
||||||
|
// New style: enums are strings.
|
||||||
|
var repr string
|
||||||
|
if err := json.Unmarshal(data, &repr); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
val, ok := m[repr]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
// Old style: enums are ints.
|
||||||
|
var val int32
|
||||||
|
if err := json.Unmarshal(data, &val); err != nil {
|
||||||
|
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this type existed for intenal-use only.
|
||||||
|
type InternalMessageInfo struct{}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||||
|
func (*InternalMessageInfo) DiscardUnknown(m Message) {
|
||||||
|
DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||||
|
func (*InternalMessageInfo) Marshal(b []byte, m Message, deterministic bool) ([]byte, error) {
|
||||||
|
return protoV2.MarshalOptions{Deterministic: deterministic}.MarshalAppend(b, MessageV2(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||||
|
func (*InternalMessageInfo) Merge(dst, src Message) {
|
||||||
|
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||||
|
func (*InternalMessageInfo) Size(m Message) int {
|
||||||
|
return protoV2.Size(MessageV2(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||||
|
func (*InternalMessageInfo) Unmarshal(m Message, b []byte) error {
|
||||||
|
return protoV2.UnmarshalOptions{Merge: true}.Unmarshal(b, MessageV2(m))
|
||||||
|
}
|
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
Normal file
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DiscardUnknown recursively discards all unknown fields from this message
|
||||||
|
// and all embedded messages.
|
||||||
|
//
|
||||||
|
// When unmarshaling a message with unrecognized fields, the tags and values
|
||||||
|
// of such fields are preserved in the Message. This allows a later call to
|
||||||
|
// marshal to be able to produce a message that continues to have those
|
||||||
|
// unrecognized fields. To avoid this, DiscardUnknown is used to
|
||||||
|
// explicitly clear the unknown fields after unmarshaling.
|
||||||
|
func DiscardUnknown(m Message) {
|
||||||
|
if m != nil {
|
||||||
|
discardUnknown(MessageReflect(m))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func discardUnknown(m protoreflect.Message) {
|
||||||
|
m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool {
|
||||||
|
switch {
|
||||||
|
// Handle singular message.
|
||||||
|
case fd.Cardinality() != protoreflect.Repeated:
|
||||||
|
if fd.Message() != nil {
|
||||||
|
discardUnknown(m.Get(fd).Message())
|
||||||
|
}
|
||||||
|
// Handle list of messages.
|
||||||
|
case fd.IsList():
|
||||||
|
if fd.Message() != nil {
|
||||||
|
ls := m.Get(fd).List()
|
||||||
|
for i := 0; i < ls.Len(); i++ {
|
||||||
|
discardUnknown(ls.Get(i).Message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle map of messages.
|
||||||
|
case fd.IsMap():
|
||||||
|
if fd.MapValue().Message() != nil {
|
||||||
|
ms := m.Get(fd).Map()
|
||||||
|
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||||
|
discardUnknown(v.Message())
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
// Discard unknown fields.
|
||||||
|
if len(m.GetUnknown()) > 0 {
|
||||||
|
m.SetUnknown(nil)
|
||||||
|
}
|
||||||
|
}
|
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
Normal file
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
// Copyright 2010 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 proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
"google.golang.org/protobuf/runtime/protoiface"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// ExtensionDesc represents an extension descriptor and
|
||||||
|
// is used to interact with an extension field in a message.
|
||||||
|
//
|
||||||
|
// Variables of this type are generated in code by protoc-gen-go.
|
||||||
|
ExtensionDesc = protoimpl.ExtensionInfo
|
||||||
|
|
||||||
|
// ExtensionRange represents a range of message extensions.
|
||||||
|
// Used in code generated by protoc-gen-go.
|
||||||
|
ExtensionRange = protoiface.ExtensionRangeV1
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this is an internal type.
|
||||||
|
Extension = protoimpl.ExtensionFieldV1
|
||||||
|
|
||||||
|
// Deprecated: Do not use; this is an internal type.
|
||||||
|
XXX_InternalExtensions = protoimpl.ExtensionFields
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrMissingExtension reports whether the extension was not present.
|
||||||
|
var ErrMissingExtension = errors.New("proto: missing extension")
|
||||||
|
|
||||||
|
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
|
||||||
|
|
||||||
|
// HasExtension reports whether the extension field is present in m
|
||||||
|
// either as an explicitly populated field or as an unknown field.
|
||||||
|
func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether any populated known field matches the field number.
|
||||||
|
xtd := xt.TypeDescriptor()
|
||||||
|
if isValidExtension(mr.Descriptor(), xtd) {
|
||||||
|
has = mr.Has(xtd)
|
||||||
|
} else {
|
||||||
|
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||||
|
has = int32(fd.Number()) == xt.Field
|
||||||
|
return !has
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether any unknown field matches the field number.
|
||||||
|
for b := mr.GetUnknown(); !has && len(b) > 0; {
|
||||||
|
num, _, n := protowire.ConsumeField(b)
|
||||||
|
has = int32(num) == xt.Field
|
||||||
|
b = b[n:]
|
||||||
|
}
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearExtension removes the extension field from m
|
||||||
|
// either as an explicitly populated field or as an unknown field.
|
||||||
|
func ClearExtension(m Message, xt *ExtensionDesc) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
xtd := xt.TypeDescriptor()
|
||||||
|
if isValidExtension(mr.Descriptor(), xtd) {
|
||||||
|
mr.Clear(xtd)
|
||||||
|
} else {
|
||||||
|
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||||
|
if int32(fd.Number()) == xt.Field {
|
||||||
|
mr.Clear(fd)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
clearUnknown(mr, fieldNum(xt.Field))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearAllExtensions clears all extensions from m.
|
||||||
|
// This includes populated fields and unknown fields in the extension range.
|
||||||
|
func ClearAllExtensions(m Message) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||||
|
if fd.IsExtension() {
|
||||||
|
mr.Clear(fd)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExtension retrieves a proto2 extended field from m.
|
||||||
|
//
|
||||||
|
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
||||||
|
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
||||||
|
// If the field is not present, then the default value is returned (if one is specified),
|
||||||
|
// otherwise ErrMissingExtension is reported.
|
||||||
|
//
|
||||||
|
// If the descriptor is type incomplete (i.e., ExtensionDesc.ExtensionType is nil),
|
||||||
|
// then GetExtension returns the raw encoded bytes for the extension field.
|
||||||
|
func GetExtension(m Message, xt *ExtensionDesc) (interface{}, error) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||||
|
return nil, errNotExtendable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the unknown fields for this extension field.
|
||||||
|
var bo protoreflect.RawFields
|
||||||
|
for bi := mr.GetUnknown(); len(bi) > 0; {
|
||||||
|
num, _, n := protowire.ConsumeField(bi)
|
||||||
|
if int32(num) == xt.Field {
|
||||||
|
bo = append(bo, bi[:n]...)
|
||||||
|
}
|
||||||
|
bi = bi[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// For type incomplete descriptors, only retrieve the unknown fields.
|
||||||
|
if xt.ExtensionType == nil {
|
||||||
|
return []byte(bo), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the extension field only exists as unknown fields, unmarshal it.
|
||||||
|
// This is rarely done since proto.Unmarshal eagerly unmarshals extensions.
|
||||||
|
xtd := xt.TypeDescriptor()
|
||||||
|
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||||
|
return nil, fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||||
|
}
|
||||||
|
if !mr.Has(xtd) && len(bo) > 0 {
|
||||||
|
m2 := mr.New()
|
||||||
|
if err := (proto.UnmarshalOptions{
|
||||||
|
Resolver: extensionResolver{xt},
|
||||||
|
}.Unmarshal(bo, m2.Interface())); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if m2.Has(xtd) {
|
||||||
|
mr.Set(xtd, m2.Get(xtd))
|
||||||
|
clearUnknown(mr, fieldNum(xt.Field))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the message has the extension field set or a default.
|
||||||
|
var pv protoreflect.Value
|
||||||
|
switch {
|
||||||
|
case mr.Has(xtd):
|
||||||
|
pv = mr.Get(xtd)
|
||||||
|
case xtd.HasDefault():
|
||||||
|
pv = xtd.Default()
|
||||||
|
default:
|
||||||
|
return nil, ErrMissingExtension
|
||||||
|
}
|
||||||
|
|
||||||
|
v := xt.InterfaceOf(pv)
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
if isScalarKind(rv.Kind()) {
|
||||||
|
rv2 := reflect.New(rv.Type())
|
||||||
|
rv2.Elem().Set(rv)
|
||||||
|
v = rv2.Interface()
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extensionResolver is a custom extension resolver that stores a single
|
||||||
|
// extension type that takes precedence over the global registry.
|
||||||
|
type extensionResolver struct{ xt protoreflect.ExtensionType }
|
||||||
|
|
||||||
|
func (r extensionResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
|
||||||
|
if xtd := r.xt.TypeDescriptor(); xtd.FullName() == field {
|
||||||
|
return r.xt, nil
|
||||||
|
}
|
||||||
|
return protoregistry.GlobalTypes.FindExtensionByName(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r extensionResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
|
||||||
|
if xtd := r.xt.TypeDescriptor(); xtd.ContainingMessage().FullName() == message && xtd.Number() == field {
|
||||||
|
return r.xt, nil
|
||||||
|
}
|
||||||
|
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExtensions returns a list of the extensions values present in m,
|
||||||
|
// corresponding with the provided list of extension descriptors, xts.
|
||||||
|
// If an extension is missing in m, the corresponding value is nil.
|
||||||
|
func GetExtensions(m Message, xts []*ExtensionDesc) ([]interface{}, error) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return nil, errNotExtendable
|
||||||
|
}
|
||||||
|
|
||||||
|
vs := make([]interface{}, len(xts))
|
||||||
|
for i, xt := range xts {
|
||||||
|
v, err := GetExtension(m, xt)
|
||||||
|
if err != nil {
|
||||||
|
if err == ErrMissingExtension {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return vs, err
|
||||||
|
}
|
||||||
|
vs[i] = v
|
||||||
|
}
|
||||||
|
return vs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExtension sets an extension field in m to the provided value.
|
||||||
|
func SetExtension(m Message, xt *ExtensionDesc, v interface{}) error {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||||
|
return errNotExtendable
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
if reflect.TypeOf(v) != reflect.TypeOf(xt.ExtensionType) {
|
||||||
|
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", v, xt.ExtensionType)
|
||||||
|
}
|
||||||
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
if rv.IsNil() {
|
||||||
|
return fmt.Errorf("proto: SetExtension called with nil value of type %T", v)
|
||||||
|
}
|
||||||
|
if isScalarKind(rv.Elem().Kind()) {
|
||||||
|
v = rv.Elem().Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xtd := xt.TypeDescriptor()
|
||||||
|
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||||
|
return fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||||
|
}
|
||||||
|
mr.Set(xtd, xt.ValueOf(v))
|
||||||
|
clearUnknown(mr, fieldNum(xt.Field))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRawExtension inserts b into the unknown fields of m.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Message.ProtoReflect.SetUnknown instead.
|
||||||
|
func SetRawExtension(m Message, fnum int32, b []byte) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the raw field is valid.
|
||||||
|
for b0 := b; len(b0) > 0; {
|
||||||
|
num, _, n := protowire.ConsumeField(b0)
|
||||||
|
if int32(num) != fnum {
|
||||||
|
panic(fmt.Sprintf("mismatching field number: got %d, want %d", num, fnum))
|
||||||
|
}
|
||||||
|
b0 = b0[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearExtension(m, &ExtensionDesc{Field: fnum})
|
||||||
|
mr.SetUnknown(append(mr.GetUnknown(), b...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtensionDescs returns a list of extension descriptors found in m,
|
||||||
|
// containing descriptors for both populated extension fields in m and
|
||||||
|
// also unknown fields of m that are in the extension range.
|
||||||
|
// For the later case, an type incomplete descriptor is provided where only
|
||||||
|
// the ExtensionDesc.Field field is populated.
|
||||||
|
// The order of the extension descriptors is undefined.
|
||||||
|
func ExtensionDescs(m Message) ([]*ExtensionDesc, error) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||||
|
return nil, errNotExtendable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect a set of known extension descriptors.
|
||||||
|
extDescs := make(map[protoreflect.FieldNumber]*ExtensionDesc)
|
||||||
|
mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||||
|
if fd.IsExtension() {
|
||||||
|
xt := fd.(protoreflect.ExtensionTypeDescriptor)
|
||||||
|
if xd, ok := xt.Type().(*ExtensionDesc); ok {
|
||||||
|
extDescs[fd.Number()] = xd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
// Collect a set of unknown extension descriptors.
|
||||||
|
extRanges := mr.Descriptor().ExtensionRanges()
|
||||||
|
for b := mr.GetUnknown(); len(b) > 0; {
|
||||||
|
num, _, n := protowire.ConsumeField(b)
|
||||||
|
if extRanges.Has(num) && extDescs[num] == nil {
|
||||||
|
extDescs[num] = nil
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transpose the set of descriptors into a list.
|
||||||
|
var xts []*ExtensionDesc
|
||||||
|
for num, xt := range extDescs {
|
||||||
|
if xt == nil {
|
||||||
|
xt = &ExtensionDesc{Field: int32(num)}
|
||||||
|
}
|
||||||
|
xts = append(xts, xt)
|
||||||
|
}
|
||||||
|
return xts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidExtension reports whether xtd is a valid extension descriptor for md.
|
||||||
|
func isValidExtension(md protoreflect.MessageDescriptor, xtd protoreflect.ExtensionTypeDescriptor) bool {
|
||||||
|
return xtd.ContainingMessage() == md && md.ExtensionRanges().Has(xtd.Number())
|
||||||
|
}
|
||||||
|
|
||||||
|
// isScalarKind reports whether k is a protobuf scalar kind (except bytes).
|
||||||
|
// This function exists for historical reasons since the representation of
|
||||||
|
// scalars differs between v1 and v2, where v1 uses *T and v2 uses T.
|
||||||
|
func isScalarKind(k reflect.Kind) bool {
|
||||||
|
switch k {
|
||||||
|
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clearUnknown removes unknown fields from m where remover.Has reports true.
|
||||||
|
func clearUnknown(m protoreflect.Message, remover interface {
|
||||||
|
Has(protoreflect.FieldNumber) bool
|
||||||
|
}) {
|
||||||
|
var bo protoreflect.RawFields
|
||||||
|
for bi := m.GetUnknown(); len(bi) > 0; {
|
||||||
|
num, _, n := protowire.ConsumeField(bi)
|
||||||
|
if !remover.Has(num) {
|
||||||
|
bo = append(bo, bi[:n]...)
|
||||||
|
}
|
||||||
|
bi = bi[n:]
|
||||||
|
}
|
||||||
|
if bi := m.GetUnknown(); len(bi) != len(bo) {
|
||||||
|
m.SetUnknown(bo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldNum protoreflect.FieldNumber
|
||||||
|
|
||||||
|
func (n1 fieldNum) Has(n2 protoreflect.FieldNumber) bool {
|
||||||
|
return protoreflect.FieldNumber(n1) == n2
|
||||||
|
}
|
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
Normal file
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
// Copyright 2010 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 proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StructProperties represents protocol buffer type information for a
|
||||||
|
// generated protobuf message in the open-struct API.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
type StructProperties struct {
|
||||||
|
// Prop are the properties for each field.
|
||||||
|
//
|
||||||
|
// Fields belonging to a oneof are stored in OneofTypes instead, with a
|
||||||
|
// single Properties representing the parent oneof held here.
|
||||||
|
//
|
||||||
|
// The order of Prop matches the order of fields in the Go struct.
|
||||||
|
// Struct fields that are not related to protobufs have a "XXX_" prefix
|
||||||
|
// in the Properties.Name and must be ignored by the user.
|
||||||
|
Prop []*Properties
|
||||||
|
|
||||||
|
// OneofTypes contains information about the oneof fields in this message.
|
||||||
|
// It is keyed by the protobuf field name.
|
||||||
|
OneofTypes map[string]*OneofProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties represents the type information for a protobuf message field.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
type Properties struct {
|
||||||
|
// Name is a placeholder name with little meaningful semantic value.
|
||||||
|
// If the name has an "XXX_" prefix, the entire Properties must be ignored.
|
||||||
|
Name string
|
||||||
|
// OrigName is the protobuf field name or oneof name.
|
||||||
|
OrigName string
|
||||||
|
// JSONName is the JSON name for the protobuf field.
|
||||||
|
JSONName string
|
||||||
|
// Enum is a placeholder name for enums.
|
||||||
|
// For historical reasons, this is neither the Go name for the enum,
|
||||||
|
// nor the protobuf name for the enum.
|
||||||
|
Enum string // Deprecated: Do not use.
|
||||||
|
// Weak contains the full name of the weakly referenced message.
|
||||||
|
Weak string
|
||||||
|
// Wire is a string representation of the wire type.
|
||||||
|
Wire string
|
||||||
|
// WireType is the protobuf wire type for the field.
|
||||||
|
WireType int
|
||||||
|
// Tag is the protobuf field number.
|
||||||
|
Tag int
|
||||||
|
// Required reports whether this is a required field.
|
||||||
|
Required bool
|
||||||
|
// Optional reports whether this is a optional field.
|
||||||
|
Optional bool
|
||||||
|
// Repeated reports whether this is a repeated field.
|
||||||
|
Repeated bool
|
||||||
|
// Packed reports whether this is a packed repeated field of scalars.
|
||||||
|
Packed bool
|
||||||
|
// Proto3 reports whether this field operates under the proto3 syntax.
|
||||||
|
Proto3 bool
|
||||||
|
// Oneof reports whether this field belongs within a oneof.
|
||||||
|
Oneof bool
|
||||||
|
|
||||||
|
// Default is the default value in string form.
|
||||||
|
Default string
|
||||||
|
// HasDefault reports whether the field has a default value.
|
||||||
|
HasDefault bool
|
||||||
|
|
||||||
|
// MapKeyProp is the properties for the key field for a map field.
|
||||||
|
MapKeyProp *Properties
|
||||||
|
// MapValProp is the properties for the value field for a map field.
|
||||||
|
MapValProp *Properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// OneofProperties represents the type information for a protobuf oneof.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
type OneofProperties struct {
|
||||||
|
// Type is a pointer to the generated wrapper type for the field value.
|
||||||
|
// This is nil for messages that are not in the open-struct API.
|
||||||
|
Type reflect.Type
|
||||||
|
// Field is the index into StructProperties.Prop for the containing oneof.
|
||||||
|
Field int
|
||||||
|
// Prop is the properties for the field.
|
||||||
|
Prop *Properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// String formats the properties in the protobuf struct field tag style.
|
||||||
|
func (p *Properties) String() string {
|
||||||
|
s := p.Wire
|
||||||
|
s += "," + strconv.Itoa(p.Tag)
|
||||||
|
if p.Required {
|
||||||
|
s += ",req"
|
||||||
|
}
|
||||||
|
if p.Optional {
|
||||||
|
s += ",opt"
|
||||||
|
}
|
||||||
|
if p.Repeated {
|
||||||
|
s += ",rep"
|
||||||
|
}
|
||||||
|
if p.Packed {
|
||||||
|
s += ",packed"
|
||||||
|
}
|
||||||
|
s += ",name=" + p.OrigName
|
||||||
|
if p.JSONName != "" {
|
||||||
|
s += ",json=" + p.JSONName
|
||||||
|
}
|
||||||
|
if len(p.Enum) > 0 {
|
||||||
|
s += ",enum=" + p.Enum
|
||||||
|
}
|
||||||
|
if len(p.Weak) > 0 {
|
||||||
|
s += ",weak=" + p.Weak
|
||||||
|
}
|
||||||
|
if p.Proto3 {
|
||||||
|
s += ",proto3"
|
||||||
|
}
|
||||||
|
if p.Oneof {
|
||||||
|
s += ",oneof"
|
||||||
|
}
|
||||||
|
if p.HasDefault {
|
||||||
|
s += ",def=" + p.Default
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse populates p by parsing a string in the protobuf struct field tag style.
|
||||||
|
func (p *Properties) Parse(tag string) {
|
||||||
|
// For example: "bytes,49,opt,name=foo,def=hello!"
|
||||||
|
for len(tag) > 0 {
|
||||||
|
i := strings.IndexByte(tag, ',')
|
||||||
|
if i < 0 {
|
||||||
|
i = len(tag)
|
||||||
|
}
|
||||||
|
switch s := tag[:i]; {
|
||||||
|
case strings.HasPrefix(s, "name="):
|
||||||
|
p.OrigName = s[len("name="):]
|
||||||
|
case strings.HasPrefix(s, "json="):
|
||||||
|
p.JSONName = s[len("json="):]
|
||||||
|
case strings.HasPrefix(s, "enum="):
|
||||||
|
p.Enum = s[len("enum="):]
|
||||||
|
case strings.HasPrefix(s, "weak="):
|
||||||
|
p.Weak = s[len("weak="):]
|
||||||
|
case strings.Trim(s, "0123456789") == "":
|
||||||
|
n, _ := strconv.ParseUint(s, 10, 32)
|
||||||
|
p.Tag = int(n)
|
||||||
|
case s == "opt":
|
||||||
|
p.Optional = true
|
||||||
|
case s == "req":
|
||||||
|
p.Required = true
|
||||||
|
case s == "rep":
|
||||||
|
p.Repeated = true
|
||||||
|
case s == "varint" || s == "zigzag32" || s == "zigzag64":
|
||||||
|
p.Wire = s
|
||||||
|
p.WireType = WireVarint
|
||||||
|
case s == "fixed32":
|
||||||
|
p.Wire = s
|
||||||
|
p.WireType = WireFixed32
|
||||||
|
case s == "fixed64":
|
||||||
|
p.Wire = s
|
||||||
|
p.WireType = WireFixed64
|
||||||
|
case s == "bytes":
|
||||||
|
p.Wire = s
|
||||||
|
p.WireType = WireBytes
|
||||||
|
case s == "group":
|
||||||
|
p.Wire = s
|
||||||
|
p.WireType = WireStartGroup
|
||||||
|
case s == "packed":
|
||||||
|
p.Packed = true
|
||||||
|
case s == "proto3":
|
||||||
|
p.Proto3 = true
|
||||||
|
case s == "oneof":
|
||||||
|
p.Oneof = true
|
||||||
|
case strings.HasPrefix(s, "def="):
|
||||||
|
// The default tag is special in that everything afterwards is the
|
||||||
|
// default regardless of the presence of commas.
|
||||||
|
p.HasDefault = true
|
||||||
|
p.Default, i = tag[len("def="):], len(tag)
|
||||||
|
}
|
||||||
|
tag = strings.TrimPrefix(tag[i:], ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init populates the properties from a protocol buffer struct tag.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
||||||
|
p.Name = name
|
||||||
|
p.OrigName = name
|
||||||
|
if tag == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.Parse(tag)
|
||||||
|
|
||||||
|
if typ != nil && typ.Kind() == reflect.Map {
|
||||||
|
p.MapKeyProp = new(Properties)
|
||||||
|
p.MapKeyProp.Init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
|
||||||
|
p.MapValProp = new(Properties)
|
||||||
|
p.MapValProp.Init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertiesCache sync.Map // map[reflect.Type]*StructProperties
|
||||||
|
|
||||||
|
// GetProperties returns the list of properties for the type represented by t,
|
||||||
|
// which must be a generated protocol buffer message in the open-struct API,
|
||||||
|
// where protobuf message fields are represented by exported Go struct fields.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protobuf reflection instead.
|
||||||
|
func GetProperties(t reflect.Type) *StructProperties {
|
||||||
|
if p, ok := propertiesCache.Load(t); ok {
|
||||||
|
return p.(*StructProperties)
|
||||||
|
}
|
||||||
|
p, _ := propertiesCache.LoadOrStore(t, newProperties(t))
|
||||||
|
return p.(*StructProperties)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProperties(t reflect.Type) *StructProperties {
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasOneof bool
|
||||||
|
prop := new(StructProperties)
|
||||||
|
|
||||||
|
// Construct a list of properties for each field in the struct.
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
p := new(Properties)
|
||||||
|
f := t.Field(i)
|
||||||
|
tagField := f.Tag.Get("protobuf")
|
||||||
|
p.Init(f.Type, f.Name, tagField, &f)
|
||||||
|
|
||||||
|
tagOneof := f.Tag.Get("protobuf_oneof")
|
||||||
|
if tagOneof != "" {
|
||||||
|
hasOneof = true
|
||||||
|
p.OrigName = tagOneof
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename unrelated struct fields with the "XXX_" prefix since so much
|
||||||
|
// user code simply checks for this to exclude special fields.
|
||||||
|
if tagField == "" && tagOneof == "" && !strings.HasPrefix(p.Name, "XXX_") {
|
||||||
|
p.Name = "XXX_" + p.Name
|
||||||
|
p.OrigName = "XXX_" + p.OrigName
|
||||||
|
} else if p.Weak != "" {
|
||||||
|
p.Name = p.OrigName // avoid possible "XXX_" prefix on weak field
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.Prop = append(prop.Prop, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a mapping of oneof field names to properties.
|
||||||
|
if hasOneof {
|
||||||
|
var oneofWrappers []interface{}
|
||||||
|
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
|
||||||
|
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
|
||||||
|
}
|
||||||
|
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
|
||||||
|
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
|
||||||
|
}
|
||||||
|
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoreflect.ProtoMessage); ok {
|
||||||
|
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
|
||||||
|
oneofWrappers = m.ProtoMessageInfo().OneofWrappers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||||
|
for _, wrapper := range oneofWrappers {
|
||||||
|
p := &OneofProperties{
|
||||||
|
Type: reflect.ValueOf(wrapper).Type(), // *T
|
||||||
|
Prop: new(Properties),
|
||||||
|
}
|
||||||
|
f := p.Type.Elem().Field(0)
|
||||||
|
p.Prop.Name = f.Name
|
||||||
|
p.Prop.Parse(f.Tag.Get("protobuf"))
|
||||||
|
|
||||||
|
// Determine the struct field that contains this oneof.
|
||||||
|
// Each wrapper is assignable to exactly one parent field.
|
||||||
|
var foundOneof bool
|
||||||
|
for i := 0; i < t.NumField() && !foundOneof; i++ {
|
||||||
|
if p.Type.AssignableTo(t.Field(i).Type) {
|
||||||
|
p.Field = i
|
||||||
|
foundOneof = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !foundOneof {
|
||||||
|
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||||
|
}
|
||||||
|
prop.OneofTypes[p.Prop.OrigName] = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sp *StructProperties) Len() int { return len(sp.Prop) }
|
||||||
|
func (sp *StructProperties) Less(i, j int) bool { return false }
|
||||||
|
func (sp *StructProperties) Swap(i, j int) { return }
|
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
Normal file
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package proto provides functionality for handling protocol buffer messages.
|
||||||
|
// In particular, it provides marshaling and unmarshaling between a protobuf
|
||||||
|
// message and the binary wire format.
|
||||||
|
//
|
||||||
|
// See https://developers.google.com/protocol-buffers/docs/gotutorial for
|
||||||
|
// more information.
|
||||||
|
//
|
||||||
|
// Deprecated: Use the "google.golang.org/protobuf/proto" package instead.
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/runtime/protoiface"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProtoPackageIsVersion1 = true
|
||||||
|
ProtoPackageIsVersion2 = true
|
||||||
|
ProtoPackageIsVersion3 = true
|
||||||
|
ProtoPackageIsVersion4 = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// GeneratedEnum is any enum type generated by protoc-gen-go
|
||||||
|
// which is a named int32 kind.
|
||||||
|
// This type exists for documentation purposes.
|
||||||
|
type GeneratedEnum interface{}
|
||||||
|
|
||||||
|
// GeneratedMessage is any message type generated by protoc-gen-go
|
||||||
|
// which is a pointer to a named struct kind.
|
||||||
|
// This type exists for documentation purposes.
|
||||||
|
type GeneratedMessage interface{}
|
||||||
|
|
||||||
|
// Message is a protocol buffer message.
|
||||||
|
//
|
||||||
|
// This is the v1 version of the message interface and is marginally better
|
||||||
|
// than an empty interface as it lacks any method to programatically interact
|
||||||
|
// with the contents of the message.
|
||||||
|
//
|
||||||
|
// A v2 message is declared in "google.golang.org/protobuf/proto".Message and
|
||||||
|
// exposes protobuf reflection as a first-class feature of the interface.
|
||||||
|
//
|
||||||
|
// To convert a v1 message to a v2 message, use the MessageV2 function.
|
||||||
|
// To convert a v2 message to a v1 message, use the MessageV1 function.
|
||||||
|
type Message = protoiface.MessageV1
|
||||||
|
|
||||||
|
// MessageV1 converts either a v1 or v2 message to a v1 message.
|
||||||
|
// It returns nil if m is nil.
|
||||||
|
func MessageV1(m GeneratedMessage) protoiface.MessageV1 {
|
||||||
|
return protoimpl.X.ProtoMessageV1Of(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageV2 converts either a v1 or v2 message to a v2 message.
|
||||||
|
// It returns nil if m is nil.
|
||||||
|
func MessageV2(m GeneratedMessage) protoV2.Message {
|
||||||
|
return protoimpl.X.ProtoMessageV2Of(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReflect returns a reflective view for a message.
|
||||||
|
// It returns nil if m is nil.
|
||||||
|
func MessageReflect(m Message) protoreflect.Message {
|
||||||
|
return protoimpl.X.MessageOf(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshaler is implemented by messages that can marshal themselves.
|
||||||
|
// This interface is used by the following functions: Size, Marshal,
|
||||||
|
// Buffer.Marshal, and Buffer.EncodeMessage.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not implement.
|
||||||
|
type Marshaler interface {
|
||||||
|
// Marshal formats the encoded bytes of the message.
|
||||||
|
// It should be deterministic and emit valid protobuf wire data.
|
||||||
|
// The caller takes ownership of the returned buffer.
|
||||||
|
Marshal() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshaler is implemented by messages that can unmarshal themselves.
|
||||||
|
// This interface is used by the following functions: Unmarshal, UnmarshalMerge,
|
||||||
|
// Buffer.Unmarshal, Buffer.DecodeMessage, and Buffer.DecodeGroup.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not implement.
|
||||||
|
type Unmarshaler interface {
|
||||||
|
// Unmarshal parses the encoded bytes of the protobuf wire input.
|
||||||
|
// The provided buffer is only valid for during method call.
|
||||||
|
// It should not reset the receiver message.
|
||||||
|
Unmarshal([]byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merger is implemented by messages that can merge themselves.
|
||||||
|
// This interface is used by the following functions: Clone and Merge.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not implement.
|
||||||
|
type Merger interface {
|
||||||
|
// Merge merges the contents of src into the receiver message.
|
||||||
|
// It clones all data structures in src such that it aliases no mutable
|
||||||
|
// memory referenced by src.
|
||||||
|
Merge(src Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequiredNotSetError is an error type returned when
|
||||||
|
// marshaling or unmarshaling a message with missing required fields.
|
||||||
|
type RequiredNotSetError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *RequiredNotSetError) Error() string {
|
||||||
|
if e.err != nil {
|
||||||
|
return e.err.Error()
|
||||||
|
}
|
||||||
|
return "proto: required field not set"
|
||||||
|
}
|
||||||
|
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRequiredNotSet(m protoV2.Message) error {
|
||||||
|
if err := protoV2.CheckInitialized(m); err != nil {
|
||||||
|
return &RequiredNotSetError{err: err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone returns a deep copy of src.
|
||||||
|
func Clone(src Message) Message {
|
||||||
|
return MessageV1(protoV2.Clone(MessageV2(src)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges src into dst, which must be messages of the same type.
|
||||||
|
//
|
||||||
|
// Populated scalar fields in src are copied to dst, while populated
|
||||||
|
// singular messages in src are merged into dst by recursively calling Merge.
|
||||||
|
// The elements of every list field in src is appended to the corresponded
|
||||||
|
// list fields in dst. The entries of every map field in src is copied into
|
||||||
|
// the corresponding map field in dst, possibly replacing existing entries.
|
||||||
|
// The unknown fields of src are appended to the unknown fields of dst.
|
||||||
|
func Merge(dst, src Message) {
|
||||||
|
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal reports whether two messages are equal.
|
||||||
|
// If two messages marshal to the same bytes under deterministic serialization,
|
||||||
|
// then Equal is guaranteed to report true.
|
||||||
|
//
|
||||||
|
// Two messages are equal if they are the same protobuf message type,
|
||||||
|
// have the same set of populated known and extension field values,
|
||||||
|
// and the same set of unknown fields values.
|
||||||
|
//
|
||||||
|
// Scalar values are compared with the equivalent of the == operator in Go,
|
||||||
|
// except bytes values which are compared using bytes.Equal and
|
||||||
|
// floating point values which specially treat NaNs as equal.
|
||||||
|
// Message values are compared by recursively calling Equal.
|
||||||
|
// Lists are equal if each element value is also equal.
|
||||||
|
// Maps are equal if they have the same set of keys, where the pair of values
|
||||||
|
// for each key is also equal.
|
||||||
|
func Equal(x, y Message) bool {
|
||||||
|
return protoV2.Equal(MessageV2(x), MessageV2(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMessageSet(md protoreflect.MessageDescriptor) bool {
|
||||||
|
ms, ok := md.(interface{ IsMessageSet() bool })
|
||||||
|
return ok && ms.IsMessageSet()
|
||||||
|
}
|
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
Normal file
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/reflect/protodesc"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
"google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// filePath is the path to the proto source file.
|
||||||
|
type filePath = string // e.g., "google/protobuf/descriptor.proto"
|
||||||
|
|
||||||
|
// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
|
||||||
|
type fileDescGZIP = []byte
|
||||||
|
|
||||||
|
var fileCache sync.Map // map[filePath]fileDescGZIP
|
||||||
|
|
||||||
|
// RegisterFile is called from generated code to register the compressed
|
||||||
|
// FileDescriptorProto with the file path for a proto source file.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
|
||||||
|
func RegisterFile(s filePath, d fileDescGZIP) {
|
||||||
|
// Decompress the descriptor.
|
||||||
|
zr, err := gzip.NewReader(bytes.NewReader(d))
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadAll(zr)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a protoreflect.FileDescriptor from the raw descriptor.
|
||||||
|
// Note that DescBuilder.Build automatically registers the constructed
|
||||||
|
// file descriptor with the v2 registry.
|
||||||
|
protoimpl.DescBuilder{RawDescriptor: b}.Build()
|
||||||
|
|
||||||
|
// Locally cache the raw descriptor form for the file.
|
||||||
|
fileCache.Store(s, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileDescriptor returns the compressed FileDescriptorProto given the file path
|
||||||
|
// for a proto source file. It returns nil if not found.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
|
||||||
|
func FileDescriptor(s filePath) fileDescGZIP {
|
||||||
|
if v, ok := fileCache.Load(s); ok {
|
||||||
|
return v.(fileDescGZIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the descriptor in the v2 registry.
|
||||||
|
var b []byte
|
||||||
|
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||||
|
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locally cache the raw descriptor form for the file.
|
||||||
|
if len(b) > 0 {
|
||||||
|
v, _ := fileCache.LoadOrStore(s, protoimpl.X.CompressGZIP(b))
|
||||||
|
return v.(fileDescGZIP)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// enumName is the name of an enum. For historical reasons, the enum name is
|
||||||
|
// neither the full Go name nor the full protobuf name of the enum.
|
||||||
|
// The name is the dot-separated combination of just the proto package that the
|
||||||
|
// enum is declared within followed by the Go type name of the generated enum.
|
||||||
|
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"
|
||||||
|
|
||||||
|
// enumsByName maps enum values by name to their numeric counterpart.
|
||||||
|
type enumsByName = map[string]int32
|
||||||
|
|
||||||
|
// enumsByNumber maps enum values by number to their name counterpart.
|
||||||
|
type enumsByNumber = map[int32]string
|
||||||
|
|
||||||
|
var enumCache sync.Map // map[enumName]enumsByName
|
||||||
|
var numFilesCache sync.Map // map[protoreflect.FullName]int
|
||||||
|
|
||||||
|
// RegisterEnum is called from the generated code to register the mapping of
|
||||||
|
// enum value names to enum numbers for the enum identified by s.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
|
||||||
|
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
|
||||||
|
if _, ok := enumCache.Load(s); ok {
|
||||||
|
panic("proto: duplicate enum registered: " + s)
|
||||||
|
}
|
||||||
|
enumCache.Store(s, m)
|
||||||
|
|
||||||
|
// This does not forward registration to the v2 registry since this API
|
||||||
|
// lacks sufficient information to construct a complete v2 enum descriptor.
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnumValueMap returns the mapping from enum value names to enum numbers for
|
||||||
|
// the enum of the given name. It returns nil if not found.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
|
||||||
|
func EnumValueMap(s enumName) enumsByName {
|
||||||
|
if v, ok := enumCache.Load(s); ok {
|
||||||
|
return v.(enumsByName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the cache is stale. If the number of files in the current
|
||||||
|
// package differs, then it means that some enums may have been recently
|
||||||
|
// registered upstream that we do not know about.
|
||||||
|
var protoPkg protoreflect.FullName
|
||||||
|
if i := strings.LastIndexByte(s, '.'); i >= 0 {
|
||||||
|
protoPkg = protoreflect.FullName(s[:i])
|
||||||
|
}
|
||||||
|
v, _ := numFilesCache.Load(protoPkg)
|
||||||
|
numFiles, _ := v.(int)
|
||||||
|
if protoregistry.GlobalFiles.NumFilesByPackage(protoPkg) == numFiles {
|
||||||
|
return nil // cache is up-to-date; was not found earlier
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the enum cache for all enums declared in the given proto package.
|
||||||
|
numFiles = 0
|
||||||
|
protoregistry.GlobalFiles.RangeFilesByPackage(protoPkg, func(fd protoreflect.FileDescriptor) bool {
|
||||||
|
walkEnums(fd, func(ed protoreflect.EnumDescriptor) {
|
||||||
|
name := protoimpl.X.LegacyEnumName(ed)
|
||||||
|
if _, ok := enumCache.Load(name); !ok {
|
||||||
|
m := make(enumsByName)
|
||||||
|
evs := ed.Values()
|
||||||
|
for i := evs.Len() - 1; i >= 0; i-- {
|
||||||
|
ev := evs.Get(i)
|
||||||
|
m[string(ev.Name())] = int32(ev.Number())
|
||||||
|
}
|
||||||
|
enumCache.LoadOrStore(name, m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
numFiles++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
numFilesCache.Store(protoPkg, numFiles)
|
||||||
|
|
||||||
|
// Check cache again for enum map.
|
||||||
|
if v, ok := enumCache.Load(s); ok {
|
||||||
|
return v.(enumsByName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// walkEnums recursively walks all enums declared in d.
|
||||||
|
func walkEnums(d interface {
|
||||||
|
Enums() protoreflect.EnumDescriptors
|
||||||
|
Messages() protoreflect.MessageDescriptors
|
||||||
|
}, f func(protoreflect.EnumDescriptor)) {
|
||||||
|
eds := d.Enums()
|
||||||
|
for i := eds.Len() - 1; i >= 0; i-- {
|
||||||
|
f(eds.Get(i))
|
||||||
|
}
|
||||||
|
mds := d.Messages()
|
||||||
|
for i := mds.Len() - 1; i >= 0; i-- {
|
||||||
|
walkEnums(mds.Get(i), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageName is the full name of protobuf message.
|
||||||
|
type messageName = string
|
||||||
|
|
||||||
|
var messageTypeCache sync.Map // map[messageName]reflect.Type
|
||||||
|
|
||||||
|
// RegisterType is called from generated code to register the message Go type
|
||||||
|
// for a message of the given name.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
|
||||||
|
func RegisterType(m Message, s messageName) {
|
||||||
|
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
|
||||||
|
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
messageTypeCache.Store(s, reflect.TypeOf(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterMapType is called from generated code to register the Go map type
|
||||||
|
// for a protobuf message representing a map entry.
|
||||||
|
//
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
func RegisterMapType(m interface{}, s messageName) {
|
||||||
|
t := reflect.TypeOf(m)
|
||||||
|
if t.Kind() != reflect.Map {
|
||||||
|
panic(fmt.Sprintf("invalid map kind: %v", t))
|
||||||
|
}
|
||||||
|
if _, ok := messageTypeCache.Load(s); ok {
|
||||||
|
panic(fmt.Errorf("proto: duplicate proto message registered: %s", s))
|
||||||
|
}
|
||||||
|
messageTypeCache.Store(s, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageType returns the message type for a named message.
|
||||||
|
// It returns nil if not found.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
|
||||||
|
func MessageType(s messageName) reflect.Type {
|
||||||
|
if v, ok := messageTypeCache.Load(s); ok {
|
||||||
|
return v.(reflect.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derive the message type from the v2 registry.
|
||||||
|
var t reflect.Type
|
||||||
|
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(s)); mt != nil {
|
||||||
|
t = messageGoType(mt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we could not get a concrete type, it is possible that it is a
|
||||||
|
// pseudo-message for a map entry.
|
||||||
|
if t == nil {
|
||||||
|
d, _ := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(s))
|
||||||
|
if md, _ := d.(protoreflect.MessageDescriptor); md != nil && md.IsMapEntry() {
|
||||||
|
kt := goTypeForField(md.Fields().ByNumber(1))
|
||||||
|
vt := goTypeForField(md.Fields().ByNumber(2))
|
||||||
|
t = reflect.MapOf(kt, vt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locally cache the message type for the given name.
|
||||||
|
if t != nil {
|
||||||
|
v, _ := messageTypeCache.LoadOrStore(s, t)
|
||||||
|
return v.(reflect.Type)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func goTypeForField(fd protoreflect.FieldDescriptor) reflect.Type {
|
||||||
|
switch k := fd.Kind(); k {
|
||||||
|
case protoreflect.EnumKind:
|
||||||
|
if et, _ := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()); et != nil {
|
||||||
|
return enumGoType(et)
|
||||||
|
}
|
||||||
|
return reflect.TypeOf(protoreflect.EnumNumber(0))
|
||||||
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
|
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()); mt != nil {
|
||||||
|
return messageGoType(mt)
|
||||||
|
}
|
||||||
|
return reflect.TypeOf((*protoreflect.Message)(nil)).Elem()
|
||||||
|
default:
|
||||||
|
return reflect.TypeOf(fd.Default().Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func enumGoType(et protoreflect.EnumType) reflect.Type {
|
||||||
|
return reflect.TypeOf(et.New(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func messageGoType(mt protoreflect.MessageType) reflect.Type {
|
||||||
|
return reflect.TypeOf(MessageV1(mt.Zero().Interface()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageName returns the full protobuf name for the given message type.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoreflect.MessageDescriptor.FullName instead.
|
||||||
|
func MessageName(m Message) messageName {
|
||||||
|
if m == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if m, ok := m.(interface{ XXX_MessageName() messageName }); ok {
|
||||||
|
return m.XXX_MessageName()
|
||||||
|
}
|
||||||
|
return messageName(protoimpl.X.MessageDescriptorOf(m).FullName())
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterExtension is called from the generated code to register
|
||||||
|
// the extension descriptor.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
|
||||||
|
func RegisterExtension(d *ExtensionDesc) {
|
||||||
|
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type extensionsByNumber = map[int32]*ExtensionDesc
|
||||||
|
|
||||||
|
var extensionCache sync.Map // map[messageName]extensionsByNumber
|
||||||
|
|
||||||
|
// RegisteredExtensions returns a map of the registered extensions for the
|
||||||
|
// provided protobuf message, indexed by the extension field number.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
|
||||||
|
func RegisteredExtensions(m Message) extensionsByNumber {
|
||||||
|
// Check whether the cache is stale. If the number of extensions for
|
||||||
|
// the given message differs, then it means that some extensions were
|
||||||
|
// recently registered upstream that we do not know about.
|
||||||
|
s := MessageName(m)
|
||||||
|
v, _ := extensionCache.Load(s)
|
||||||
|
xs, _ := v.(extensionsByNumber)
|
||||||
|
if protoregistry.GlobalTypes.NumExtensionsByMessage(protoreflect.FullName(s)) == len(xs) {
|
||||||
|
return xs // cache is up-to-date
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache is stale, re-compute the extensions map.
|
||||||
|
xs = make(extensionsByNumber)
|
||||||
|
protoregistry.GlobalTypes.RangeExtensionsByMessage(protoreflect.FullName(s), func(xt protoreflect.ExtensionType) bool {
|
||||||
|
if xd, ok := xt.(*ExtensionDesc); ok {
|
||||||
|
xs[int32(xt.TypeDescriptor().Number())] = xd
|
||||||
|
} else {
|
||||||
|
// TODO: This implies that the protoreflect.ExtensionType is a
|
||||||
|
// custom type not generated by protoc-gen-go. We could try and
|
||||||
|
// convert the type to an ExtensionDesc.
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
extensionCache.Store(s, xs)
|
||||||
|
return xs
|
||||||
|
}
|
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
Normal file
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
Normal file
@ -0,0 +1,801 @@
|
|||||||
|
// Copyright 2010 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 proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrapTextUnmarshalV2 = false
|
||||||
|
|
||||||
|
// ParseError is returned by UnmarshalText.
|
||||||
|
type ParseError struct {
|
||||||
|
Message string
|
||||||
|
|
||||||
|
// Deprecated: Do not use.
|
||||||
|
Line, Offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ParseError) Error() string {
|
||||||
|
if wrapTextUnmarshalV2 {
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
if e.Line == 1 {
|
||||||
|
return fmt.Sprintf("line 1.%d: %v", e.Offset, e.Message)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("line %d: %v", e.Line, e.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText parses a proto text formatted string into m.
|
||||||
|
func UnmarshalText(s string, m Message) error {
|
||||||
|
if u, ok := m.(encoding.TextUnmarshaler); ok {
|
||||||
|
return u.UnmarshalText([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Reset()
|
||||||
|
mi := MessageV2(m)
|
||||||
|
|
||||||
|
if wrapTextUnmarshalV2 {
|
||||||
|
err := prototext.UnmarshalOptions{
|
||||||
|
AllowPartial: true,
|
||||||
|
}.Unmarshal([]byte(s), mi)
|
||||||
|
if err != nil {
|
||||||
|
return &ParseError{Message: err.Error()}
|
||||||
|
}
|
||||||
|
return checkRequiredNotSet(mi)
|
||||||
|
} else {
|
||||||
|
if err := newTextParser(s).unmarshalMessage(mi.ProtoReflect(), ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return checkRequiredNotSet(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type textParser struct {
|
||||||
|
s string // remaining input
|
||||||
|
done bool // whether the parsing is finished (success or error)
|
||||||
|
backed bool // whether back() was called
|
||||||
|
offset, line int
|
||||||
|
cur token
|
||||||
|
}
|
||||||
|
|
||||||
|
type token struct {
|
||||||
|
value string
|
||||||
|
err *ParseError
|
||||||
|
line int // line number
|
||||||
|
offset int // byte number from start of input, not start of line
|
||||||
|
unquoted string // the unquoted version of value, if it was a quoted string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTextParser(s string) *textParser {
|
||||||
|
p := new(textParser)
|
||||||
|
p.s = s
|
||||||
|
p.line = 1
|
||||||
|
p.cur.line = 1
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) unmarshalMessage(m protoreflect.Message, terminator string) (err error) {
|
||||||
|
md := m.Descriptor()
|
||||||
|
fds := md.Fields()
|
||||||
|
|
||||||
|
// A struct is a sequence of "name: value", terminated by one of
|
||||||
|
// '>' or '}', or the end of the input. A name may also be
|
||||||
|
// "[extension]" or "[type/url]".
|
||||||
|
//
|
||||||
|
// The whole struct can also be an expanded Any message, like:
|
||||||
|
// [type/url] < ... struct contents ... >
|
||||||
|
seen := make(map[protoreflect.FieldNumber]bool)
|
||||||
|
for {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
if tok.value == terminator {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if tok.value == "[" {
|
||||||
|
if err := p.unmarshalExtensionOrAny(m, seen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a normal, non-extension field.
|
||||||
|
name := protoreflect.Name(tok.value)
|
||||||
|
fd := fds.ByName(name)
|
||||||
|
switch {
|
||||||
|
case fd == nil:
|
||||||
|
gd := fds.ByName(protoreflect.Name(strings.ToLower(string(name))))
|
||||||
|
if gd != nil && gd.Kind() == protoreflect.GroupKind && gd.Message().Name() == name {
|
||||||
|
fd = gd
|
||||||
|
}
|
||||||
|
case fd.Kind() == protoreflect.GroupKind && fd.Message().Name() != name:
|
||||||
|
fd = nil
|
||||||
|
case fd.IsWeak() && fd.Message().IsPlaceholder():
|
||||||
|
fd = nil
|
||||||
|
}
|
||||||
|
if fd == nil {
|
||||||
|
typeName := string(md.FullName())
|
||||||
|
if m, ok := m.Interface().(Message); ok {
|
||||||
|
t := reflect.TypeOf(m)
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
typeName = t.Elem().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.errorf("unknown field name %q in %v", name, typeName)
|
||||||
|
}
|
||||||
|
if od := fd.ContainingOneof(); od != nil && m.WhichOneof(od) != nil {
|
||||||
|
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, od.Name())
|
||||||
|
}
|
||||||
|
if fd.Cardinality() != protoreflect.Repeated && seen[fd.Number()] {
|
||||||
|
return p.errorf("non-repeated field %q was repeated", fd.Name())
|
||||||
|
}
|
||||||
|
seen[fd.Number()] = true
|
||||||
|
|
||||||
|
// Consume any colon.
|
||||||
|
if err := p.checkForColon(fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse into the field.
|
||||||
|
v := m.Get(fd)
|
||||||
|
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||||
|
v = m.Mutable(fd)
|
||||||
|
}
|
||||||
|
if v, err = p.unmarshalValue(v, fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
|
||||||
|
if err := p.consumeOptionalSeparator(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) unmarshalExtensionOrAny(m protoreflect.Message, seen map[protoreflect.FieldNumber]bool) error {
|
||||||
|
name, err := p.consumeExtensionOrAnyName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it contains a slash, it's an Any type URL.
|
||||||
|
if slashIdx := strings.LastIndex(name, "/"); slashIdx >= 0 {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
// consume an optional colon
|
||||||
|
if tok.value == ":" {
|
||||||
|
tok = p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var terminator string
|
||||||
|
switch tok.value {
|
||||||
|
case "<":
|
||||||
|
terminator = ">"
|
||||||
|
case "{":
|
||||||
|
terminator = "}"
|
||||||
|
default:
|
||||||
|
return p.errorf("expected '{' or '<', found %q", tok.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
mt, err := protoregistry.GlobalTypes.FindMessageByURL(name)
|
||||||
|
if err != nil {
|
||||||
|
return p.errorf("unrecognized message %q in google.protobuf.Any", name[slashIdx+len("/"):])
|
||||||
|
}
|
||||||
|
m2 := mt.New()
|
||||||
|
if err := p.unmarshalMessage(m2, terminator); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b, err := protoV2.Marshal(m2.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return p.errorf("failed to marshal message of type %q: %v", name[slashIdx+len("/"):], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
urlFD := m.Descriptor().Fields().ByName("type_url")
|
||||||
|
valFD := m.Descriptor().Fields().ByName("value")
|
||||||
|
if seen[urlFD.Number()] {
|
||||||
|
return p.errorf("Any message unpacked multiple times, or %q already set", urlFD.Name())
|
||||||
|
}
|
||||||
|
if seen[valFD.Number()] {
|
||||||
|
return p.errorf("Any message unpacked multiple times, or %q already set", valFD.Name())
|
||||||
|
}
|
||||||
|
m.Set(urlFD, protoreflect.ValueOfString(name))
|
||||||
|
m.Set(valFD, protoreflect.ValueOfBytes(b))
|
||||||
|
seen[urlFD.Number()] = true
|
||||||
|
seen[valFD.Number()] = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
xname := protoreflect.FullName(name)
|
||||||
|
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
|
||||||
|
if xt == nil && isMessageSet(m.Descriptor()) {
|
||||||
|
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
|
||||||
|
}
|
||||||
|
if xt == nil {
|
||||||
|
return p.errorf("unrecognized extension %q", name)
|
||||||
|
}
|
||||||
|
fd := xt.TypeDescriptor()
|
||||||
|
if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
|
||||||
|
return p.errorf("extension field %q does not extend message %q", name, m.Descriptor().FullName())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.checkForColon(fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v := m.Get(fd)
|
||||||
|
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||||
|
v = m.Mutable(fd)
|
||||||
|
}
|
||||||
|
v, err = p.unmarshalValue(v, fd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Set(fd, v)
|
||||||
|
return p.consumeOptionalSeparator()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) unmarshalValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return v, tok.err
|
||||||
|
}
|
||||||
|
if tok.value == "" {
|
||||||
|
return v, p.errorf("unexpected EOF")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case fd.IsList():
|
||||||
|
lv := v.List()
|
||||||
|
var err error
|
||||||
|
if tok.value == "[" {
|
||||||
|
// Repeated field with list notation, like [1,2,3].
|
||||||
|
for {
|
||||||
|
vv := lv.NewElement()
|
||||||
|
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
lv.Append(vv)
|
||||||
|
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return v, tok.err
|
||||||
|
}
|
||||||
|
if tok.value == "]" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if tok.value != "," {
|
||||||
|
return v, p.errorf("Expected ']' or ',' found %q", tok.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// One value of the repeated field.
|
||||||
|
p.back()
|
||||||
|
vv := lv.NewElement()
|
||||||
|
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
lv.Append(vv)
|
||||||
|
return v, nil
|
||||||
|
case fd.IsMap():
|
||||||
|
// The map entry should be this sequence of tokens:
|
||||||
|
// < key : KEY value : VALUE >
|
||||||
|
// However, implementations may omit key or value, and technically
|
||||||
|
// we should support them in any order.
|
||||||
|
var terminator string
|
||||||
|
switch tok.value {
|
||||||
|
case "<":
|
||||||
|
terminator = ">"
|
||||||
|
case "{":
|
||||||
|
terminator = "}"
|
||||||
|
default:
|
||||||
|
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyFD := fd.MapKey()
|
||||||
|
valFD := fd.MapValue()
|
||||||
|
|
||||||
|
mv := v.Map()
|
||||||
|
kv := keyFD.Default()
|
||||||
|
vv := mv.NewValue()
|
||||||
|
for {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return v, tok.err
|
||||||
|
}
|
||||||
|
if tok.value == terminator {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
switch tok.value {
|
||||||
|
case "key":
|
||||||
|
if err := p.consumeToken(":"); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
if kv, err = p.unmarshalSingularValue(kv, keyFD); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
if err := p.consumeOptionalSeparator(); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
case "value":
|
||||||
|
if err := p.checkForColon(valFD); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
if vv, err = p.unmarshalSingularValue(vv, valFD); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
if err := p.consumeOptionalSeparator(); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
p.back()
|
||||||
|
return v, p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.Set(kv.MapKey(), vv)
|
||||||
|
return v, nil
|
||||||
|
default:
|
||||||
|
p.back()
|
||||||
|
return p.unmarshalSingularValue(v, fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return v, tok.err
|
||||||
|
}
|
||||||
|
if tok.value == "" {
|
||||||
|
return v, p.errorf("unexpected EOF")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fd.Kind() {
|
||||||
|
case protoreflect.BoolKind:
|
||||||
|
switch tok.value {
|
||||||
|
case "true", "1", "t", "True":
|
||||||
|
return protoreflect.ValueOfBool(true), nil
|
||||||
|
case "false", "0", "f", "False":
|
||||||
|
return protoreflect.ValueOfBool(false), nil
|
||||||
|
}
|
||||||
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
||||||
|
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||||
|
return protoreflect.ValueOfInt32(int32(x)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The C++ parser accepts large positive hex numbers that uses
|
||||||
|
// two's complement arithmetic to represent negative numbers.
|
||||||
|
// This feature is here for backwards compatibility with C++.
|
||||||
|
if strings.HasPrefix(tok.value, "0x") {
|
||||||
|
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||||
|
return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||||
|
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
|
||||||
|
return protoreflect.ValueOfInt64(int64(x)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The C++ parser accepts large positive hex numbers that uses
|
||||||
|
// two's complement arithmetic to represent negative numbers.
|
||||||
|
// This feature is here for backwards compatibility with C++.
|
||||||
|
if strings.HasPrefix(tok.value, "0x") {
|
||||||
|
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||||
|
return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
||||||
|
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||||
|
return protoreflect.ValueOfUint32(uint32(x)), nil
|
||||||
|
}
|
||||||
|
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||||
|
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||||
|
return protoreflect.ValueOfUint64(uint64(x)), nil
|
||||||
|
}
|
||||||
|
case protoreflect.FloatKind:
|
||||||
|
// Ignore 'f' for compatibility with output generated by C++,
|
||||||
|
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||||
|
v := tok.value
|
||||||
|
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||||
|
v = v[:len(v)-len("f")]
|
||||||
|
}
|
||||||
|
if x, err := strconv.ParseFloat(v, 32); err == nil {
|
||||||
|
return protoreflect.ValueOfFloat32(float32(x)), nil
|
||||||
|
}
|
||||||
|
case protoreflect.DoubleKind:
|
||||||
|
// Ignore 'f' for compatibility with output generated by C++,
|
||||||
|
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||||
|
v := tok.value
|
||||||
|
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||||
|
v = v[:len(v)-len("f")]
|
||||||
|
}
|
||||||
|
if x, err := strconv.ParseFloat(v, 64); err == nil {
|
||||||
|
return protoreflect.ValueOfFloat64(float64(x)), nil
|
||||||
|
}
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
if isQuote(tok.value[0]) {
|
||||||
|
return protoreflect.ValueOfString(tok.unquoted), nil
|
||||||
|
}
|
||||||
|
case protoreflect.BytesKind:
|
||||||
|
if isQuote(tok.value[0]) {
|
||||||
|
return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
|
||||||
|
}
|
||||||
|
case protoreflect.EnumKind:
|
||||||
|
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||||
|
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
|
||||||
|
}
|
||||||
|
vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
|
||||||
|
if vd != nil {
|
||||||
|
return protoreflect.ValueOfEnum(vd.Number()), nil
|
||||||
|
}
|
||||||
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
|
var terminator string
|
||||||
|
switch tok.value {
|
||||||
|
case "{":
|
||||||
|
terminator = "}"
|
||||||
|
case "<":
|
||||||
|
terminator = ">"
|
||||||
|
default:
|
||||||
|
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||||
|
}
|
||||||
|
err := p.unmarshalMessage(v.Message(), terminator)
|
||||||
|
return v, err
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
|
||||||
|
}
|
||||||
|
return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume a ':' from the input stream (if the next token is a colon),
|
||||||
|
// returning an error if a colon is needed but not present.
|
||||||
|
func (p *textParser) checkForColon(fd protoreflect.FieldDescriptor) *ParseError {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
if tok.value != ":" {
|
||||||
|
if fd.Message() == nil {
|
||||||
|
return p.errorf("expected ':', found %q", tok.value)
|
||||||
|
}
|
||||||
|
p.back()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// consumeExtensionOrAnyName consumes an extension name or an Any type URL and
|
||||||
|
// the following ']'. It returns the name or URL consumed.
|
||||||
|
func (p *textParser) consumeExtensionOrAnyName() (string, error) {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return "", tok.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If extension name or type url is quoted, it's a single token.
|
||||||
|
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
||||||
|
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return name, p.consumeToken("]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume everything up to "]"
|
||||||
|
var parts []string
|
||||||
|
for tok.value != "]" {
|
||||||
|
parts = append(parts, tok.value)
|
||||||
|
tok = p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
||||||
|
}
|
||||||
|
if p.done && tok.value != "]" {
|
||||||
|
return "", p.errorf("unclosed type_url or extension name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(parts, ""), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// consumeOptionalSeparator consumes an optional semicolon or comma.
|
||||||
|
// It is used in unmarshalMessage to provide backward compatibility.
|
||||||
|
func (p *textParser) consumeOptionalSeparator() error {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
if tok.value != ";" && tok.value != "," {
|
||||||
|
p.back()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
|
||||||
|
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
|
||||||
|
p.cur.err = pe
|
||||||
|
p.done = true
|
||||||
|
return pe
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) skipWhitespace() {
|
||||||
|
i := 0
|
||||||
|
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
||||||
|
if p.s[i] == '#' {
|
||||||
|
// comment; skip to end of line or input
|
||||||
|
for i < len(p.s) && p.s[i] != '\n' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == len(p.s) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.s[i] == '\n' {
|
||||||
|
p.line++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
p.offset += i
|
||||||
|
p.s = p.s[i:len(p.s)]
|
||||||
|
if len(p.s) == 0 {
|
||||||
|
p.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) advance() {
|
||||||
|
// Skip whitespace
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start of non-whitespace
|
||||||
|
p.cur.err = nil
|
||||||
|
p.cur.offset, p.cur.line = p.offset, p.line
|
||||||
|
p.cur.unquoted = ""
|
||||||
|
switch p.s[0] {
|
||||||
|
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
||||||
|
// Single symbol
|
||||||
|
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
||||||
|
case '"', '\'':
|
||||||
|
// Quoted string
|
||||||
|
i := 1
|
||||||
|
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
|
||||||
|
if p.s[i] == '\\' && i+1 < len(p.s) {
|
||||||
|
// skip escaped char
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(p.s) || p.s[i] != p.s[0] {
|
||||||
|
p.errorf("unmatched quote")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
|
||||||
|
if err != nil {
|
||||||
|
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
||||||
|
p.cur.unquoted = unq
|
||||||
|
default:
|
||||||
|
i := 0
|
||||||
|
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
p.errorf("unexpected byte %#x", p.s[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
||||||
|
}
|
||||||
|
p.offset += len(p.cur.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back off the parser by one token. Can only be done between calls to next().
|
||||||
|
// It makes the next advance() a no-op.
|
||||||
|
func (p *textParser) back() { p.backed = true }
|
||||||
|
|
||||||
|
// Advances the parser and returns the new current token.
|
||||||
|
func (p *textParser) next() *token {
|
||||||
|
if p.backed || p.done {
|
||||||
|
p.backed = false
|
||||||
|
return &p.cur
|
||||||
|
}
|
||||||
|
p.advance()
|
||||||
|
if p.done {
|
||||||
|
p.cur.value = ""
|
||||||
|
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
|
||||||
|
// Look for multiple quoted strings separated by whitespace,
|
||||||
|
// and concatenate them.
|
||||||
|
cat := p.cur
|
||||||
|
for {
|
||||||
|
p.skipWhitespace()
|
||||||
|
if p.done || !isQuote(p.s[0]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.advance()
|
||||||
|
if p.cur.err != nil {
|
||||||
|
return &p.cur
|
||||||
|
}
|
||||||
|
cat.value += " " + p.cur.value
|
||||||
|
cat.unquoted += p.cur.unquoted
|
||||||
|
}
|
||||||
|
p.done = false // parser may have seen EOF, but we want to return cat
|
||||||
|
p.cur = cat
|
||||||
|
}
|
||||||
|
return &p.cur
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *textParser) consumeToken(s string) error {
|
||||||
|
tok := p.next()
|
||||||
|
if tok.err != nil {
|
||||||
|
return tok.err
|
||||||
|
}
|
||||||
|
if tok.value != s {
|
||||||
|
p.back()
|
||||||
|
return p.errorf("expected %q, found %q", s, tok.value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errBadUTF8 = errors.New("proto: bad UTF-8")
|
||||||
|
|
||||||
|
func unquoteC(s string, quote rune) (string, error) {
|
||||||
|
// This is based on C++'s tokenizer.cc.
|
||||||
|
// Despite its name, this is *not* parsing C syntax.
|
||||||
|
// For instance, "\0" is an invalid quoted string.
|
||||||
|
|
||||||
|
// Avoid allocation in trivial cases.
|
||||||
|
simple := true
|
||||||
|
for _, r := range s {
|
||||||
|
if r == '\\' || r == quote {
|
||||||
|
simple = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if simple {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 0, 3*len(s)/2)
|
||||||
|
for len(s) > 0 {
|
||||||
|
r, n := utf8.DecodeRuneInString(s)
|
||||||
|
if r == utf8.RuneError && n == 1 {
|
||||||
|
return "", errBadUTF8
|
||||||
|
}
|
||||||
|
s = s[n:]
|
||||||
|
if r != '\\' {
|
||||||
|
if r < utf8.RuneSelf {
|
||||||
|
buf = append(buf, byte(r))
|
||||||
|
} else {
|
||||||
|
buf = append(buf, string(r)...)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, tail, err := unescape(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
buf = append(buf, ch...)
|
||||||
|
s = tail
|
||||||
|
}
|
||||||
|
return string(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unescape(s string) (ch string, tail string, err error) {
|
||||||
|
r, n := utf8.DecodeRuneInString(s)
|
||||||
|
if r == utf8.RuneError && n == 1 {
|
||||||
|
return "", "", errBadUTF8
|
||||||
|
}
|
||||||
|
s = s[n:]
|
||||||
|
switch r {
|
||||||
|
case 'a':
|
||||||
|
return "\a", s, nil
|
||||||
|
case 'b':
|
||||||
|
return "\b", s, nil
|
||||||
|
case 'f':
|
||||||
|
return "\f", s, nil
|
||||||
|
case 'n':
|
||||||
|
return "\n", s, nil
|
||||||
|
case 'r':
|
||||||
|
return "\r", s, nil
|
||||||
|
case 't':
|
||||||
|
return "\t", s, nil
|
||||||
|
case 'v':
|
||||||
|
return "\v", s, nil
|
||||||
|
case '?':
|
||||||
|
return "?", s, nil // trigraph workaround
|
||||||
|
case '\'', '"', '\\':
|
||||||
|
return string(r), s, nil
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
|
if len(s) < 2 {
|
||||||
|
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
||||||
|
}
|
||||||
|
ss := string(r) + s[:2]
|
||||||
|
s = s[2:]
|
||||||
|
i, err := strconv.ParseUint(ss, 8, 8)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
||||||
|
}
|
||||||
|
return string([]byte{byte(i)}), s, nil
|
||||||
|
case 'x', 'X', 'u', 'U':
|
||||||
|
var n int
|
||||||
|
switch r {
|
||||||
|
case 'x', 'X':
|
||||||
|
n = 2
|
||||||
|
case 'u':
|
||||||
|
n = 4
|
||||||
|
case 'U':
|
||||||
|
n = 8
|
||||||
|
}
|
||||||
|
if len(s) < n {
|
||||||
|
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
||||||
|
}
|
||||||
|
ss := s[:n]
|
||||||
|
s = s[n:]
|
||||||
|
i, err := strconv.ParseUint(ss, 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
||||||
|
}
|
||||||
|
if r == 'x' || r == 'X' {
|
||||||
|
return string([]byte{byte(i)}), s, nil
|
||||||
|
}
|
||||||
|
if i > utf8.MaxRune {
|
||||||
|
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
||||||
|
}
|
||||||
|
return string(rune(i)), s, nil
|
||||||
|
}
|
||||||
|
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIdentOrNumberChar(c byte) bool {
|
||||||
|
switch {
|
||||||
|
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
||||||
|
return true
|
||||||
|
case '0' <= c && c <= '9':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
switch c {
|
||||||
|
case '-', '+', '.', '_':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWhitespace(c byte) bool {
|
||||||
|
switch c {
|
||||||
|
case ' ', '\t', '\n', '\r':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isQuote(c byte) bool {
|
||||||
|
switch c {
|
||||||
|
case '"', '\'':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
Normal file
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
// Copyright 2010 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 proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrapTextMarshalV2 = false
|
||||||
|
|
||||||
|
// TextMarshaler is a configurable text format marshaler.
|
||||||
|
type TextMarshaler struct {
|
||||||
|
Compact bool // use compact text format (one line)
|
||||||
|
ExpandAny bool // expand google.protobuf.Any messages of known types
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal writes the proto text format of m to w.
|
||||||
|
func (tm *TextMarshaler) Marshal(w io.Writer, m Message) error {
|
||||||
|
b, err := tm.marshal(m)
|
||||||
|
if len(b) > 0 {
|
||||||
|
if _, err := w.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text returns a proto text formatted string of m.
|
||||||
|
func (tm *TextMarshaler) Text(m Message) string {
|
||||||
|
b, _ := tm.marshal(m)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TextMarshaler) marshal(m Message) ([]byte, error) {
|
||||||
|
mr := MessageReflect(m)
|
||||||
|
if mr == nil || !mr.IsValid() {
|
||||||
|
return []byte("<nil>"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if wrapTextMarshalV2 {
|
||||||
|
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||||
|
return m.MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := prototext.MarshalOptions{
|
||||||
|
AllowPartial: true,
|
||||||
|
EmitUnknown: true,
|
||||||
|
}
|
||||||
|
if !tm.Compact {
|
||||||
|
opts.Indent = " "
|
||||||
|
}
|
||||||
|
if !tm.ExpandAny {
|
||||||
|
opts.Resolver = (*protoregistry.Types)(nil)
|
||||||
|
}
|
||||||
|
return opts.Marshal(mr.Interface())
|
||||||
|
} else {
|
||||||
|
w := &textWriter{
|
||||||
|
compact: tm.Compact,
|
||||||
|
expandAny: tm.ExpandAny,
|
||||||
|
complete: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||||
|
b, err := m.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
w.Write(b)
|
||||||
|
return w.buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := w.writeMessage(mr)
|
||||||
|
return w.buf, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultTextMarshaler = TextMarshaler{}
|
||||||
|
compactTextMarshaler = TextMarshaler{Compact: true}
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarshalText writes the proto text format of m to w.
|
||||||
|
func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
|
||||||
|
|
||||||
|
// MarshalTextString returns a proto text formatted string of m.
|
||||||
|
func MarshalTextString(m Message) string { return defaultTextMarshaler.Text(m) }
|
||||||
|
|
||||||
|
// CompactText writes the compact proto text format of m to w.
|
||||||
|
func CompactText(w io.Writer, m Message) error { return compactTextMarshaler.Marshal(w, m) }
|
||||||
|
|
||||||
|
// CompactTextString returns a compact proto text formatted string of m.
|
||||||
|
func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
|
||||||
|
|
||||||
|
var (
|
||||||
|
newline = []byte("\n")
|
||||||
|
endBraceNewline = []byte("}\n")
|
||||||
|
posInf = []byte("inf")
|
||||||
|
negInf = []byte("-inf")
|
||||||
|
nan = []byte("nan")
|
||||||
|
)
|
||||||
|
|
||||||
|
// textWriter is an io.Writer that tracks its indentation level.
|
||||||
|
type textWriter struct {
|
||||||
|
compact bool // same as TextMarshaler.Compact
|
||||||
|
expandAny bool // same as TextMarshaler.ExpandAny
|
||||||
|
complete bool // whether the current position is a complete line
|
||||||
|
indent int // indentation level; never negative
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) Write(p []byte) (n int, _ error) {
|
||||||
|
newlines := bytes.Count(p, newline)
|
||||||
|
if newlines == 0 {
|
||||||
|
if !w.compact && w.complete {
|
||||||
|
w.writeIndent()
|
||||||
|
}
|
||||||
|
w.buf = append(w.buf, p...)
|
||||||
|
w.complete = false
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
frags := bytes.SplitN(p, newline, newlines+1)
|
||||||
|
if w.compact {
|
||||||
|
for i, frag := range frags {
|
||||||
|
if i > 0 {
|
||||||
|
w.buf = append(w.buf, ' ')
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
w.buf = append(w.buf, frag...)
|
||||||
|
n += len(frag)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, frag := range frags {
|
||||||
|
if w.complete {
|
||||||
|
w.writeIndent()
|
||||||
|
}
|
||||||
|
w.buf = append(w.buf, frag...)
|
||||||
|
n += len(frag)
|
||||||
|
if i+1 < len(frags) {
|
||||||
|
w.buf = append(w.buf, '\n')
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.complete = len(frags[len(frags)-1]) == 0
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) WriteByte(c byte) error {
|
||||||
|
if w.compact && c == '\n' {
|
||||||
|
c = ' '
|
||||||
|
}
|
||||||
|
if !w.compact && w.complete {
|
||||||
|
w.writeIndent()
|
||||||
|
}
|
||||||
|
w.buf = append(w.buf, c)
|
||||||
|
w.complete = c == '\n'
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeName(fd protoreflect.FieldDescriptor) {
|
||||||
|
if !w.compact && w.complete {
|
||||||
|
w.writeIndent()
|
||||||
|
}
|
||||||
|
w.complete = false
|
||||||
|
|
||||||
|
if fd.Kind() != protoreflect.GroupKind {
|
||||||
|
w.buf = append(w.buf, fd.Name()...)
|
||||||
|
w.WriteByte(':')
|
||||||
|
} else {
|
||||||
|
// Use message type name for group field name.
|
||||||
|
w.buf = append(w.buf, fd.Message().Name()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !w.compact {
|
||||||
|
w.WriteByte(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requiresQuotes(u string) bool {
|
||||||
|
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
||||||
|
for _, ch := range u {
|
||||||
|
switch {
|
||||||
|
case ch == '.' || ch == '/' || ch == '_':
|
||||||
|
continue
|
||||||
|
case '0' <= ch && ch <= '9':
|
||||||
|
continue
|
||||||
|
case 'A' <= ch && ch <= 'Z':
|
||||||
|
continue
|
||||||
|
case 'a' <= ch && ch <= 'z':
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeProto3Any writes an expanded google.protobuf.Any message.
|
||||||
|
//
|
||||||
|
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
|
||||||
|
// required messages are not linked in).
|
||||||
|
//
|
||||||
|
// It returns (true, error) when sv was written in expanded format or an error
|
||||||
|
// was encountered.
|
||||||
|
func (w *textWriter) writeProto3Any(m protoreflect.Message) (bool, error) {
|
||||||
|
md := m.Descriptor()
|
||||||
|
fdURL := md.Fields().ByName("type_url")
|
||||||
|
fdVal := md.Fields().ByName("value")
|
||||||
|
|
||||||
|
url := m.Get(fdURL).String()
|
||||||
|
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b := m.Get(fdVal).Bytes()
|
||||||
|
m2 := mt.New()
|
||||||
|
if err := proto.Unmarshal(b, m2.Interface()); err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
w.Write([]byte("["))
|
||||||
|
if requiresQuotes(url) {
|
||||||
|
w.writeQuotedString(url)
|
||||||
|
} else {
|
||||||
|
w.Write([]byte(url))
|
||||||
|
}
|
||||||
|
if w.compact {
|
||||||
|
w.Write([]byte("]:<"))
|
||||||
|
} else {
|
||||||
|
w.Write([]byte("]: <\n"))
|
||||||
|
w.indent++
|
||||||
|
}
|
||||||
|
if err := w.writeMessage(m2); err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
if w.compact {
|
||||||
|
w.Write([]byte("> "))
|
||||||
|
} else {
|
||||||
|
w.indent--
|
||||||
|
w.Write([]byte(">\n"))
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeMessage(m protoreflect.Message) error {
|
||||||
|
md := m.Descriptor()
|
||||||
|
if w.expandAny && md.FullName() == "google.protobuf.Any" {
|
||||||
|
if canExpand, err := w.writeProto3Any(m); canExpand {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fds := md.Fields()
|
||||||
|
for i := 0; i < fds.Len(); {
|
||||||
|
fd := fds.Get(i)
|
||||||
|
if od := fd.ContainingOneof(); od != nil {
|
||||||
|
fd = m.WhichOneof(od)
|
||||||
|
i += od.Fields().Len()
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if fd == nil || !m.Has(fd) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case fd.IsList():
|
||||||
|
lv := m.Get(fd).List()
|
||||||
|
for j := 0; j < lv.Len(); j++ {
|
||||||
|
w.writeName(fd)
|
||||||
|
v := lv.Get(j)
|
||||||
|
if err := w.writeSingularValue(v, fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
case fd.IsMap():
|
||||||
|
kfd := fd.MapKey()
|
||||||
|
vfd := fd.MapValue()
|
||||||
|
mv := m.Get(fd).Map()
|
||||||
|
|
||||||
|
type entry struct{ key, val protoreflect.Value }
|
||||||
|
var entries []entry
|
||||||
|
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
|
||||||
|
entries = append(entries, entry{k.Value(), v})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Slice(entries, func(i, j int) bool {
|
||||||
|
switch kfd.Kind() {
|
||||||
|
case protoreflect.BoolKind:
|
||||||
|
return !entries[i].key.Bool() && entries[j].key.Bool()
|
||||||
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||||
|
return entries[i].key.Int() < entries[j].key.Int()
|
||||||
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||||
|
return entries[i].key.Uint() < entries[j].key.Uint()
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
return entries[i].key.String() < entries[j].key.String()
|
||||||
|
default:
|
||||||
|
panic("invalid kind")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, entry := range entries {
|
||||||
|
w.writeName(fd)
|
||||||
|
w.WriteByte('<')
|
||||||
|
if !w.compact {
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
w.indent++
|
||||||
|
w.writeName(kfd)
|
||||||
|
if err := w.writeSingularValue(entry.key, kfd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
w.writeName(vfd)
|
||||||
|
if err := w.writeSingularValue(entry.val, vfd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
w.indent--
|
||||||
|
w.WriteByte('>')
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
w.writeName(fd)
|
||||||
|
if err := w.writeSingularValue(m.Get(fd), fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b := m.GetUnknown(); len(b) > 0 {
|
||||||
|
w.writeUnknownFields(b)
|
||||||
|
}
|
||||||
|
return w.writeExtensions(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||||
|
switch fd.Kind() {
|
||||||
|
case protoreflect.FloatKind, protoreflect.DoubleKind:
|
||||||
|
switch vf := v.Float(); {
|
||||||
|
case math.IsInf(vf, +1):
|
||||||
|
w.Write(posInf)
|
||||||
|
case math.IsInf(vf, -1):
|
||||||
|
w.Write(negInf)
|
||||||
|
case math.IsNaN(vf):
|
||||||
|
w.Write(nan)
|
||||||
|
default:
|
||||||
|
fmt.Fprint(w, v.Interface())
|
||||||
|
}
|
||||||
|
case protoreflect.StringKind:
|
||||||
|
// NOTE: This does not validate UTF-8 for historical reasons.
|
||||||
|
w.writeQuotedString(string(v.String()))
|
||||||
|
case protoreflect.BytesKind:
|
||||||
|
w.writeQuotedString(string(v.Bytes()))
|
||||||
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
|
var bra, ket byte = '<', '>'
|
||||||
|
if fd.Kind() == protoreflect.GroupKind {
|
||||||
|
bra, ket = '{', '}'
|
||||||
|
}
|
||||||
|
w.WriteByte(bra)
|
||||||
|
if !w.compact {
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
w.indent++
|
||||||
|
m := v.Message()
|
||||||
|
if m2, ok := m.Interface().(encoding.TextMarshaler); ok {
|
||||||
|
b, err := m2.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.Write(b)
|
||||||
|
} else {
|
||||||
|
w.writeMessage(m)
|
||||||
|
}
|
||||||
|
w.indent--
|
||||||
|
w.WriteByte(ket)
|
||||||
|
case protoreflect.EnumKind:
|
||||||
|
if ev := fd.Enum().Values().ByNumber(v.Enum()); ev != nil {
|
||||||
|
fmt.Fprint(w, ev.Name())
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(w, v.Enum())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fmt.Fprint(w, v.Interface())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeQuotedString writes a quoted string in the protocol buffer text format.
|
||||||
|
func (w *textWriter) writeQuotedString(s string) {
|
||||||
|
w.WriteByte('"')
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
switch c := s[i]; c {
|
||||||
|
case '\n':
|
||||||
|
w.buf = append(w.buf, `\n`...)
|
||||||
|
case '\r':
|
||||||
|
w.buf = append(w.buf, `\r`...)
|
||||||
|
case '\t':
|
||||||
|
w.buf = append(w.buf, `\t`...)
|
||||||
|
case '"':
|
||||||
|
w.buf = append(w.buf, `\"`...)
|
||||||
|
case '\\':
|
||||||
|
w.buf = append(w.buf, `\\`...)
|
||||||
|
default:
|
||||||
|
if isPrint := c >= 0x20 && c < 0x7f; isPrint {
|
||||||
|
w.buf = append(w.buf, c)
|
||||||
|
} else {
|
||||||
|
w.buf = append(w.buf, fmt.Sprintf(`\%03o`, c)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteByte('"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeUnknownFields(b []byte) {
|
||||||
|
if !w.compact {
|
||||||
|
fmt.Fprintf(w, "/* %d unknown bytes */\n", len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(b) > 0 {
|
||||||
|
num, wtyp, n := protowire.ConsumeTag(b)
|
||||||
|
if n < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
|
||||||
|
if wtyp == protowire.EndGroupType {
|
||||||
|
w.indent--
|
||||||
|
w.Write(endBraceNewline)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, num)
|
||||||
|
if wtyp != protowire.StartGroupType {
|
||||||
|
w.WriteByte(':')
|
||||||
|
}
|
||||||
|
if !w.compact || wtyp == protowire.StartGroupType {
|
||||||
|
w.WriteByte(' ')
|
||||||
|
}
|
||||||
|
switch wtyp {
|
||||||
|
case protowire.VarintType:
|
||||||
|
v, n := protowire.ConsumeVarint(b)
|
||||||
|
if n < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
fmt.Fprint(w, v)
|
||||||
|
case protowire.Fixed32Type:
|
||||||
|
v, n := protowire.ConsumeFixed32(b)
|
||||||
|
if n < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
fmt.Fprint(w, v)
|
||||||
|
case protowire.Fixed64Type:
|
||||||
|
v, n := protowire.ConsumeFixed64(b)
|
||||||
|
if n < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
fmt.Fprint(w, v)
|
||||||
|
case protowire.BytesType:
|
||||||
|
v, n := protowire.ConsumeBytes(b)
|
||||||
|
if n < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
fmt.Fprintf(w, "%q", v)
|
||||||
|
case protowire.StartGroupType:
|
||||||
|
w.WriteByte('{')
|
||||||
|
w.indent++
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(w, "/* unknown wire type %d */", wtyp)
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeExtensions writes all the extensions in m.
|
||||||
|
func (w *textWriter) writeExtensions(m protoreflect.Message) error {
|
||||||
|
md := m.Descriptor()
|
||||||
|
if md.ExtensionRanges().Len() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ext struct {
|
||||||
|
desc protoreflect.FieldDescriptor
|
||||||
|
val protoreflect.Value
|
||||||
|
}
|
||||||
|
var exts []ext
|
||||||
|
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||||
|
if fd.IsExtension() {
|
||||||
|
exts = append(exts, ext{fd, v})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Slice(exts, func(i, j int) bool {
|
||||||
|
return exts[i].desc.Number() < exts[j].desc.Number()
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, ext := range exts {
|
||||||
|
// For message set, use the name of the message as the extension name.
|
||||||
|
name := string(ext.desc.FullName())
|
||||||
|
if isMessageSet(ext.desc.ContainingMessage()) {
|
||||||
|
name = strings.TrimSuffix(name, ".message_set_extension")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ext.desc.IsList() {
|
||||||
|
if err := w.writeSingularExtension(name, ext.val, ext.desc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lv := ext.val.List()
|
||||||
|
for i := 0; i < lv.Len(); i++ {
|
||||||
|
if err := w.writeSingularExtension(name, lv.Get(i), ext.desc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeSingularExtension(name string, v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||||
|
fmt.Fprintf(w, "[%s]:", name)
|
||||||
|
if !w.compact {
|
||||||
|
w.WriteByte(' ')
|
||||||
|
}
|
||||||
|
if err := w.writeSingularValue(v, fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.WriteByte('\n')
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *textWriter) writeIndent() {
|
||||||
|
if !w.complete {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < w.indent*2; i++ {
|
||||||
|
w.buf = append(w.buf, ' ')
|
||||||
|
}
|
||||||
|
w.complete = false
|
||||||
|
}
|
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
Normal file
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoV2 "google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/runtime/protoiface"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Size returns the size in bytes of the wire-format encoding of m.
|
||||||
|
func Size(m Message) int {
|
||||||
|
if m == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
mi := MessageV2(m)
|
||||||
|
return protoV2.Size(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal returns the wire-format encoding of m.
|
||||||
|
func Marshal(m Message) ([]byte, error) {
|
||||||
|
b, err := marshalAppend(nil, m, false)
|
||||||
|
if b == nil {
|
||||||
|
b = zeroBytes
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroBytes = make([]byte, 0, 0)
|
||||||
|
|
||||||
|
func marshalAppend(buf []byte, m Message, deterministic bool) ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return nil, ErrNil
|
||||||
|
}
|
||||||
|
mi := MessageV2(m)
|
||||||
|
nbuf, err := protoV2.MarshalOptions{
|
||||||
|
Deterministic: deterministic,
|
||||||
|
AllowPartial: true,
|
||||||
|
}.MarshalAppend(buf, mi)
|
||||||
|
if err != nil {
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
|
if len(buf) == len(nbuf) {
|
||||||
|
if !mi.ProtoReflect().IsValid() {
|
||||||
|
return buf, ErrNil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nbuf, checkRequiredNotSet(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal parses a wire-format message in b and places the decoded results in m.
|
||||||
|
//
|
||||||
|
// Unmarshal resets m before starting to unmarshal, so any existing data in m is always
|
||||||
|
// removed. Use UnmarshalMerge to preserve and append to existing data.
|
||||||
|
func Unmarshal(b []byte, m Message) error {
|
||||||
|
m.Reset()
|
||||||
|
return UnmarshalMerge(b, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalMerge parses a wire-format message in b and places the decoded results in m.
|
||||||
|
func UnmarshalMerge(b []byte, m Message) error {
|
||||||
|
mi := MessageV2(m)
|
||||||
|
out, err := protoV2.UnmarshalOptions{
|
||||||
|
AllowPartial: true,
|
||||||
|
Merge: true,
|
||||||
|
}.UnmarshalState(protoiface.UnmarshalInput{
|
||||||
|
Buf: b,
|
||||||
|
Message: mi.ProtoReflect(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if out.Flags&protoiface.UnmarshalInitialized > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return checkRequiredNotSet(mi)
|
||||||
|
}
|
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
Normal file
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
// Bool stores v in a new bool value and returns a pointer to it.
|
||||||
|
func Bool(v bool) *bool { return &v }
|
||||||
|
|
||||||
|
// Int stores v in a new int32 value and returns a pointer to it.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int32 instead.
|
||||||
|
func Int(v int) *int32 { return Int32(int32(v)) }
|
||||||
|
|
||||||
|
// Int32 stores v in a new int32 value and returns a pointer to it.
|
||||||
|
func Int32(v int32) *int32 { return &v }
|
||||||
|
|
||||||
|
// Int64 stores v in a new int64 value and returns a pointer to it.
|
||||||
|
func Int64(v int64) *int64 { return &v }
|
||||||
|
|
||||||
|
// Uint32 stores v in a new uint32 value and returns a pointer to it.
|
||||||
|
func Uint32(v uint32) *uint32 { return &v }
|
||||||
|
|
||||||
|
// Uint64 stores v in a new uint64 value and returns a pointer to it.
|
||||||
|
func Uint64(v uint64) *uint64 { return &v }
|
||||||
|
|
||||||
|
// Float32 stores v in a new float32 value and returns a pointer to it.
|
||||||
|
func Float32(v float32) *float32 { return &v }
|
||||||
|
|
||||||
|
// Float64 stores v in a new float64 value and returns a pointer to it.
|
||||||
|
func Float64(v float64) *float64 { return &v }
|
||||||
|
|
||||||
|
// String stores v in a new string value and returns a pointer to it.
|
||||||
|
func String(v string) *string { return &v }
|
179
vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
Normal file
179
vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ptypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
|
||||||
|
anypb "github.com/golang/protobuf/ptypes/any"
|
||||||
|
)
|
||||||
|
|
||||||
|
const urlPrefix = "type.googleapis.com/"
|
||||||
|
|
||||||
|
// AnyMessageName returns the message name contained in an anypb.Any message.
|
||||||
|
// Most type assertions should use the Is function instead.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the any.MessageName method instead.
|
||||||
|
func AnyMessageName(any *anypb.Any) (string, error) {
|
||||||
|
name, err := anyMessageName(any)
|
||||||
|
return string(name), err
|
||||||
|
}
|
||||||
|
func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
|
||||||
|
if any == nil {
|
||||||
|
return "", fmt.Errorf("message is nil")
|
||||||
|
}
|
||||||
|
name := protoreflect.FullName(any.TypeUrl)
|
||||||
|
if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 {
|
||||||
|
name = name[i+len("/"):]
|
||||||
|
}
|
||||||
|
if !name.IsValid() {
|
||||||
|
return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalAny marshals the given message m into an anypb.Any message.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the anypb.New function instead.
|
||||||
|
func MarshalAny(m proto.Message) (*anypb.Any, error) {
|
||||||
|
switch dm := m.(type) {
|
||||||
|
case DynamicAny:
|
||||||
|
m = dm.Message
|
||||||
|
case *DynamicAny:
|
||||||
|
if dm == nil {
|
||||||
|
return nil, proto.ErrNil
|
||||||
|
}
|
||||||
|
m = dm.Message
|
||||||
|
}
|
||||||
|
b, err := proto.Marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns a new message of the type specified in an anypb.Any message.
|
||||||
|
// It returns protoregistry.NotFound if the corresponding message type could not
|
||||||
|
// be resolved in the global registry.
|
||||||
|
//
|
||||||
|
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
|
||||||
|
// to resolve the message name and create a new instance of it.
|
||||||
|
func Empty(any *anypb.Any) (proto.Message, error) {
|
||||||
|
name, err := anyMessageName(any)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mt, err := protoregistry.GlobalTypes.FindMessageByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return proto.MessageV1(mt.New().Interface()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalAny unmarshals the encoded value contained in the anypb.Any message
|
||||||
|
// into the provided message m. It returns an error if the target message
|
||||||
|
// does not match the type in the Any message or if an unmarshal error occurs.
|
||||||
|
//
|
||||||
|
// The target message m may be a *DynamicAny message. If the underlying message
|
||||||
|
// type could not be resolved, then this returns protoregistry.NotFound.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the any.UnmarshalTo method instead.
|
||||||
|
func UnmarshalAny(any *anypb.Any, m proto.Message) error {
|
||||||
|
if dm, ok := m.(*DynamicAny); ok {
|
||||||
|
if dm.Message == nil {
|
||||||
|
var err error
|
||||||
|
dm.Message, err = Empty(any)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m = dm.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
anyName, err := AnyMessageName(any)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
msgName := proto.MessageName(m)
|
||||||
|
if anyName != msgName {
|
||||||
|
return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName)
|
||||||
|
}
|
||||||
|
return proto.Unmarshal(any.Value, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is reports whether the Any message contains a message of the specified type.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the any.MessageIs method instead.
|
||||||
|
func Is(any *anypb.Any, m proto.Message) bool {
|
||||||
|
if any == nil || m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
name := proto.MessageName(m)
|
||||||
|
if !strings.HasSuffix(any.TypeUrl, name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
// DynamicAny is a value that can be passed to UnmarshalAny to automatically
|
||||||
|
// allocate a proto.Message for the type specified in an anypb.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)
|
||||||
|
//
|
||||||
|
// Deprecated: Use the any.UnmarshalNew method instead to unmarshal
|
||||||
|
// the any message contents into a new instance of the underlying message.
|
||||||
|
type DynamicAny struct{ proto.Message }
|
||||||
|
|
||||||
|
func (m DynamicAny) String() string {
|
||||||
|
if m.Message == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return m.Message.String()
|
||||||
|
}
|
||||||
|
func (m DynamicAny) Reset() {
|
||||||
|
if m.Message == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.Message.Reset()
|
||||||
|
}
|
||||||
|
func (m DynamicAny) ProtoMessage() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (m DynamicAny) ProtoReflect() protoreflect.Message {
|
||||||
|
if m.Message == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return dynamicAny{proto.MessageReflect(m.Message)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type dynamicAny struct{ protoreflect.Message }
|
||||||
|
|
||||||
|
func (m dynamicAny) Type() protoreflect.MessageType {
|
||||||
|
return dynamicAnyType{m.Message.Type()}
|
||||||
|
}
|
||||||
|
func (m dynamicAny) New() protoreflect.Message {
|
||||||
|
return dynamicAnyType{m.Message.Type()}.New()
|
||||||
|
}
|
||||||
|
func (m dynamicAny) Interface() protoreflect.ProtoMessage {
|
||||||
|
return DynamicAny{proto.MessageV1(m.Message.Interface())}
|
||||||
|
}
|
||||||
|
|
||||||
|
type dynamicAnyType struct{ protoreflect.MessageType }
|
||||||
|
|
||||||
|
func (t dynamicAnyType) New() protoreflect.Message {
|
||||||
|
return dynamicAny{t.MessageType.New()}
|
||||||
|
}
|
||||||
|
func (t dynamicAnyType) Zero() protoreflect.Message {
|
||||||
|
return dynamicAny{t.MessageType.Zero()}
|
||||||
|
}
|
62
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
generated
vendored
Normal file
62
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: github.com/golang/protobuf/ptypes/any/any.proto
|
||||||
|
|
||||||
|
package any
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
anypb "google.golang.org/protobuf/types/known/anypb"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Symbols defined in public import of google/protobuf/any.proto.
|
||||||
|
|
||||||
|
type Any = anypb.Any
|
||||||
|
|
||||||
|
var File_github_com_golang_protobuf_ptypes_any_any_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c,
|
||||||
|
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79,
|
||||||
|
0x70, 0x65, 0x73, 0x2f, 0x61, 0x6e, 0x79, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
|
0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x2b, 0x5a, 0x29,
|
||||||
|
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e,
|
||||||
|
0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65,
|
||||||
|
0x73, 0x2f, 0x61, 0x6e, 0x79, 0x3b, 0x61, 0x6e, 0x79, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||||
|
0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = []interface{}{}
|
||||||
|
var file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_github_com_golang_protobuf_ptypes_any_any_proto_init() }
|
||||||
|
func file_github_com_golang_protobuf_ptypes_any_any_proto_init() {
|
||||||
|
if File_github_com_golang_protobuf_ptypes_any_any_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes,
|
||||||
|
DependencyIndexes: file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_github_com_golang_protobuf_ptypes_any_any_proto = out.File
|
||||||
|
file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = nil
|
||||||
|
}
|
10
vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
Normal file
10
vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package ptypes provides functionality for interacting with well-known types.
|
||||||
|
//
|
||||||
|
// Deprecated: Well-known types have specialized functionality directly
|
||||||
|
// injected into the generated packages for each message type.
|
||||||
|
// See the deprecation notice for each function for the suggested alternative.
|
||||||
|
package ptypes
|
76
vendor/github.com/golang/protobuf/ptypes/duration.go
generated
vendored
Normal file
76
vendor/github.com/golang/protobuf/ptypes/duration.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ptypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
durationpb "github.com/golang/protobuf/ptypes/duration"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Range of google.protobuf.Duration as specified in duration.proto.
|
||||||
|
// This is about 10,000 years in seconds.
|
||||||
|
const (
|
||||||
|
maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
|
||||||
|
minSeconds = -maxSeconds
|
||||||
|
)
|
||||||
|
|
||||||
|
// Duration converts a durationpb.Duration to a time.Duration.
|
||||||
|
// Duration returns an error if dur is invalid or overflows a time.Duration.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead.
|
||||||
|
func Duration(dur *durationpb.Duration) (time.Duration, error) {
|
||||||
|
if err := validateDuration(dur); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d := time.Duration(dur.Seconds) * time.Second
|
||||||
|
if int64(d/time.Second) != dur.Seconds {
|
||||||
|
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur)
|
||||||
|
}
|
||||||
|
if dur.Nanos != 0 {
|
||||||
|
d += time.Duration(dur.Nanos) * time.Nanosecond
|
||||||
|
if (d < 0) != (dur.Nanos < 0) {
|
||||||
|
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationProto converts a time.Duration to a durationpb.Duration.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the durationpb.New function instead.
|
||||||
|
func DurationProto(d time.Duration) *durationpb.Duration {
|
||||||
|
nanos := d.Nanoseconds()
|
||||||
|
secs := nanos / 1e9
|
||||||
|
nanos -= secs * 1e9
|
||||||
|
return &durationpb.Duration{
|
||||||
|
Seconds: int64(secs),
|
||||||
|
Nanos: int32(nanos),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateDuration determines whether the durationpb.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
|
||||||
|
// Note that the range of durationpb.Duration is about 10,000 years,
|
||||||
|
// while the range of time.Duration is about 290 years.
|
||||||
|
func validateDuration(dur *durationpb.Duration) error {
|
||||||
|
if dur == nil {
|
||||||
|
return errors.New("duration: nil Duration")
|
||||||
|
}
|
||||||
|
if dur.Seconds < minSeconds || dur.Seconds > maxSeconds {
|
||||||
|
return fmt.Errorf("duration: %v: seconds out of range", dur)
|
||||||
|
}
|
||||||
|
if dur.Nanos <= -1e9 || dur.Nanos >= 1e9 {
|
||||||
|
return fmt.Errorf("duration: %v: nanos out of range", dur)
|
||||||
|
}
|
||||||
|
// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
|
||||||
|
if (dur.Seconds < 0 && dur.Nanos > 0) || (dur.Seconds > 0 && dur.Nanos < 0) {
|
||||||
|
return fmt.Errorf("duration: %v: seconds and nanos have different signs", dur)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
63
vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
generated
vendored
Normal file
63
vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: github.com/golang/protobuf/ptypes/duration/duration.proto
|
||||||
|
|
||||||
|
package duration
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Symbols defined in public import of google/protobuf/duration.proto.
|
||||||
|
|
||||||
|
type Duration = durationpb.Duration
|
||||||
|
|
||||||
|
var File_github_com_golang_protobuf_ptypes_duration_duration_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c,
|
||||||
|
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79,
|
||||||
|
0x70, 0x65, 0x73, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x75, 0x72,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f,
|
||||||
|
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67,
|
||||||
|
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
|
||||||
|
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||||
|
0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
|
||||||
|
0x6f, 0x6e, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = []interface{}{}
|
||||||
|
var file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() }
|
||||||
|
func file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() {
|
||||||
|
if File_github_com_golang_protobuf_ptypes_duration_duration_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes,
|
||||||
|
DependencyIndexes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_github_com_golang_protobuf_ptypes_duration_duration_proto = out.File
|
||||||
|
file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = nil
|
||||||
|
}
|
112
vendor/github.com/golang/protobuf/ptypes/timestamp.go
generated
vendored
Normal file
112
vendor/github.com/golang/protobuf/ptypes/timestamp.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ptypes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
timestamppb "github.com/golang/protobuf/ptypes/timestamp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Range of google.protobuf.Duration as specified in timestamp.proto.
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timestamp converts a timestamppb.Timestamp 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.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead.
|
||||||
|
func Timestamp(ts *timestamppb.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.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the timestamppb.Now function instead.
|
||||||
|
func TimestampNow() *timestamppb.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.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the timestamppb.New function instead.
|
||||||
|
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
|
||||||
|
ts := ×tamppb.Timestamp{
|
||||||
|
Seconds: t.Unix(),
|
||||||
|
Nanos: int32(t.Nanosecond()),
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
// Deprecated: Call the ts.AsTime method instead,
|
||||||
|
// followed by a call to the Format method on the time.Time value.
|
||||||
|
func TimestampString(ts *timestamppb.Timestamp) string {
|
||||||
|
t, err := Timestamp(ts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("(%v)", err)
|
||||||
|
}
|
||||||
|
return t.Format(time.RFC3339Nano)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 *timestamppb.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
|
||||||
|
}
|
64
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
Normal file
64
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
|
||||||
|
|
||||||
|
package timestamp
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Symbols defined in public import of google/protobuf/timestamp.proto.
|
||||||
|
|
||||||
|
type Timestamp = timestamppb.Timestamp
|
||||||
|
|
||||||
|
var File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c,
|
||||||
|
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79,
|
||||||
|
0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x74, 0x69,
|
||||||
|
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67,
|
||||||
|
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
|
||||||
|
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x37,
|
||||||
|
0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c,
|
||||||
|
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79,
|
||||||
|
0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x3b, 0x74, 0x69,
|
||||||
|
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = []interface{}{}
|
||||||
|
var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() }
|
||||||
|
func file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() {
|
||||||
|
if File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes,
|
||||||
|
DependencyIndexes: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto = out.File
|
||||||
|
file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = nil
|
||||||
|
file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs = nil
|
||||||
|
}
|
14
vendor/github.com/jackc/pgx/v5/CHANGELOG.md
generated
vendored
14
vendor/github.com/jackc/pgx/v5/CHANGELOG.md
generated
vendored
@ -1,3 +1,17 @@
|
|||||||
|
# 5.5.0 (November 4, 2023)
|
||||||
|
|
||||||
|
* Add CollectExactlyOneRow. (Julien GOTTELAND)
|
||||||
|
* Add OpenDBFromPool to create *database/sql.DB from *pgxpool.Pool. (Lev Zakharov)
|
||||||
|
* Prepare can automatically choose statement name based on sql. This makes it easier to explicitly manage prepared statements.
|
||||||
|
* Statement cache now uses deterministic, stable statement names.
|
||||||
|
* database/sql prepared statement names are deterministically generated.
|
||||||
|
* Fix: SendBatch wasn't respecting context cancellation.
|
||||||
|
* Fix: Timeout error from pipeline is now normalized.
|
||||||
|
* Fix: database/sql encoding json.RawMessage to []byte.
|
||||||
|
* CancelRequest: Wait for the cancel request to be acknowledged by the server. This should improve PgBouncer compatibility. (Anton Levakin)
|
||||||
|
* stdlib: Use Ping instead of CheckConn in ResetSession
|
||||||
|
* Add json.Marshaler and json.Unmarshaler for Float4, Float8 (Kirill Mironov)
|
||||||
|
|
||||||
# 5.4.3 (August 5, 2023)
|
# 5.4.3 (August 5, 2023)
|
||||||
|
|
||||||
* Fix: QCharArrayOID was defined with the wrong OID (Christoph Engelbert)
|
* Fix: QCharArrayOID was defined with the wrong OID (Christoph Engelbert)
|
||||||
|
6
vendor/github.com/jackc/pgx/v5/README.md
generated
vendored
6
vendor/github.com/jackc/pgx/v5/README.md
generated
vendored
@ -86,9 +86,13 @@ It is also possible to use the `database/sql` interface and convert a connection
|
|||||||
|
|
||||||
See CONTRIBUTING.md for setup instructions.
|
See CONTRIBUTING.md for setup instructions.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
See the presentation at Golang Estonia, [PGX Top to Bottom](https://www.youtube.com/watch?v=sXMSWhcHCf8) for a description of pgx architecture.
|
||||||
|
|
||||||
## Supported Go and PostgreSQL Versions
|
## Supported Go and PostgreSQL Versions
|
||||||
|
|
||||||
pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.19 and higher and PostgreSQL 11 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
|
pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.20 and higher and PostgreSQL 11 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
|
||||||
|
|
||||||
## Version Policy
|
## Version Policy
|
||||||
|
|
||||||
|
76
vendor/github.com/jackc/pgx/v5/conn.go
generated
vendored
76
vendor/github.com/jackc/pgx/v5/conn.go
generated
vendored
@ -2,6 +2,8 @@ package pgx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -35,7 +37,7 @@ type ConnConfig struct {
|
|||||||
|
|
||||||
// DefaultQueryExecMode controls the default mode for executing queries. By default pgx uses the extended protocol
|
// DefaultQueryExecMode controls the default mode for executing queries. By default pgx uses the extended protocol
|
||||||
// and automatically prepares and caches prepared statements. However, this may be incompatible with proxies such as
|
// and automatically prepares and caches prepared statements. However, this may be incompatible with proxies such as
|
||||||
// PGBouncer. In this case it may be preferrable to use QueryExecModeExec or QueryExecModeSimpleProtocol. The same
|
// PGBouncer. In this case it may be preferable to use QueryExecModeExec or QueryExecModeSimpleProtocol. The same
|
||||||
// functionality can be controlled on a per query basis by passing a QueryExecMode as the first query argument.
|
// functionality can be controlled on a per query basis by passing a QueryExecMode as the first query argument.
|
||||||
DefaultQueryExecMode QueryExecMode
|
DefaultQueryExecMode QueryExecMode
|
||||||
|
|
||||||
@ -99,8 +101,12 @@ func (ident Identifier) Sanitize() string {
|
|||||||
return strings.Join(parts, ".")
|
return strings.Join(parts, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
// ErrNoRows occurs when rows are expected but none are returned.
|
// ErrNoRows occurs when rows are expected but none are returned.
|
||||||
var ErrNoRows = errors.New("no rows in result set")
|
ErrNoRows = errors.New("no rows in result set")
|
||||||
|
// ErrTooManyRows occurs when more rows than expected are returned.
|
||||||
|
ErrTooManyRows = errors.New("too many rows in result set")
|
||||||
|
)
|
||||||
|
|
||||||
var errDisabledStatementCache = fmt.Errorf("cannot use QueryExecModeCacheStatement with disabled statement cache")
|
var errDisabledStatementCache = fmt.Errorf("cannot use QueryExecModeCacheStatement with disabled statement cache")
|
||||||
var errDisabledDescriptionCache = fmt.Errorf("cannot use QueryExecModeCacheDescribe with disabled description cache")
|
var errDisabledDescriptionCache = fmt.Errorf("cannot use QueryExecModeCacheDescribe with disabled description cache")
|
||||||
@ -269,7 +275,7 @@ func connect(ctx context.Context, config *ConnConfig) (c *Conn, err error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes a connection. It is safe to call Close on a already closed
|
// Close closes a connection. It is safe to call Close on an already closed
|
||||||
// connection.
|
// connection.
|
||||||
func (c *Conn) Close(ctx context.Context) error {
|
func (c *Conn) Close(ctx context.Context) error {
|
||||||
if c.IsClosed() {
|
if c.IsClosed() {
|
||||||
@ -280,12 +286,15 @@ func (c *Conn) Close(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare creates a prepared statement with name and sql. sql can contain placeholders
|
// Prepare creates a prepared statement with name and sql. sql can contain placeholders for bound parameters. These
|
||||||
// for bound parameters. These placeholders are referenced positional as $1, $2, etc.
|
// placeholders are referenced positionally as $1, $2, etc. name can be used instead of sql with Query, QueryRow, and
|
||||||
|
// Exec to execute the statement. It can also be used with Batch.Queue.
|
||||||
//
|
//
|
||||||
// Prepare is idempotent; i.e. it is safe to call Prepare multiple times with the same
|
// The underlying PostgreSQL identifier for the prepared statement will be name if name != sql or a digest of sql if
|
||||||
// name and sql arguments. This allows a code path to Prepare and Query/Exec without
|
// name == sql.
|
||||||
// concern for if the statement has already been prepared.
|
//
|
||||||
|
// Prepare is idempotent; i.e. it is safe to call Prepare multiple times with the same name and sql arguments. This
|
||||||
|
// allows a code path to Prepare and Query/Exec without concern for if the statement has already been prepared.
|
||||||
func (c *Conn) Prepare(ctx context.Context, name, sql string) (sd *pgconn.StatementDescription, err error) {
|
func (c *Conn) Prepare(ctx context.Context, name, sql string) (sd *pgconn.StatementDescription, err error) {
|
||||||
if c.prepareTracer != nil {
|
if c.prepareTracer != nil {
|
||||||
ctx = c.prepareTracer.TracePrepareStart(ctx, c, TracePrepareStartData{Name: name, SQL: sql})
|
ctx = c.prepareTracer.TracePrepareStart(ctx, c, TracePrepareStartData{Name: name, SQL: sql})
|
||||||
@ -307,22 +316,38 @@ func (c *Conn) Prepare(ctx context.Context, name, sql string) (sd *pgconn.Statem
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
sd, err = c.pgConn.Prepare(ctx, name, sql, nil)
|
var psName, psKey string
|
||||||
|
if name == sql {
|
||||||
|
digest := sha256.Sum256([]byte(sql))
|
||||||
|
psName = "stmt_" + hex.EncodeToString(digest[0:24])
|
||||||
|
psKey = sql
|
||||||
|
} else {
|
||||||
|
psName = name
|
||||||
|
psKey = name
|
||||||
|
}
|
||||||
|
|
||||||
|
sd, err = c.pgConn.Prepare(ctx, psName, sql, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if name != "" {
|
if psKey != "" {
|
||||||
c.preparedStatements[name] = sd
|
c.preparedStatements[psKey] = sd
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd, nil
|
return sd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deallocate released a prepared statement
|
// Deallocate releases a prepared statement.
|
||||||
func (c *Conn) Deallocate(ctx context.Context, name string) error {
|
func (c *Conn) Deallocate(ctx context.Context, name string) error {
|
||||||
|
var psName string
|
||||||
|
if sd, ok := c.preparedStatements[name]; ok {
|
||||||
delete(c.preparedStatements, name)
|
delete(c.preparedStatements, name)
|
||||||
_, err := c.pgConn.Exec(ctx, "deallocate "+quoteIdentifier(name)).ReadAll()
|
psName = sd.Name
|
||||||
|
} else {
|
||||||
|
psName = name
|
||||||
|
}
|
||||||
|
_, err := c.pgConn.Exec(ctx, "deallocate "+quoteIdentifier(psName)).ReadAll()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +486,7 @@ optionLoop:
|
|||||||
}
|
}
|
||||||
sd := c.statementCache.Get(sql)
|
sd := c.statementCache.Get(sql)
|
||||||
if sd == nil {
|
if sd == nil {
|
||||||
sd, err = c.Prepare(ctx, stmtcache.NextStatementName(), sql)
|
sd, err = c.Prepare(ctx, stmtcache.StatementName(sql), sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pgconn.CommandTag{}, err
|
return pgconn.CommandTag{}, err
|
||||||
}
|
}
|
||||||
@ -573,13 +598,16 @@ type QueryExecMode int32
|
|||||||
const (
|
const (
|
||||||
_ QueryExecMode = iota
|
_ QueryExecMode = iota
|
||||||
|
|
||||||
// Automatically prepare and cache statements. This uses the extended protocol. Queries are executed in a single
|
// Automatically prepare and cache statements. This uses the extended protocol. Queries are executed in a single round
|
||||||
// round trip after the statement is cached. This is the default.
|
// trip after the statement is cached. This is the default. If the database schema is modified or the search_path is
|
||||||
|
// changed after a statement is cached then the first execution of a previously cached query may fail. e.g. If the
|
||||||
|
// number of columns returned by a "SELECT *" changes or the type of a column is changed.
|
||||||
QueryExecModeCacheStatement
|
QueryExecModeCacheStatement
|
||||||
|
|
||||||
// Cache statement descriptions (i.e. argument and result types) and assume they do not change. This uses the
|
// Cache statement descriptions (i.e. argument and result types) and assume they do not change. This uses the extended
|
||||||
// extended protocol. Queries are executed in a single round trip after the description is cached. If the database
|
// protocol. Queries are executed in a single round trip after the description is cached. If the database schema is
|
||||||
// schema is modified or the search_path is changed this may result in undetected result decoding errors.
|
// modified or the search_path is changed after a statement is cached then the first execution of a previously cached
|
||||||
|
// query may fail. e.g. If the number of columns returned by a "SELECT *" changes or the type of a column is changed.
|
||||||
QueryExecModeCacheDescribe
|
QueryExecModeCacheDescribe
|
||||||
|
|
||||||
// Get the statement description on every execution. This uses the extended protocol. Queries require two round trips
|
// Get the statement description on every execution. This uses the extended protocol. Queries require two round trips
|
||||||
@ -592,13 +620,13 @@ const (
|
|||||||
// Assume the PostgreSQL query parameter types based on the Go type of the arguments. This uses the extended protocol
|
// Assume the PostgreSQL query parameter types based on the Go type of the arguments. This uses the extended protocol
|
||||||
// with text formatted parameters and results. Queries are executed in a single round trip. Type mappings can be
|
// with text formatted parameters and results. Queries are executed in a single round trip. Type mappings can be
|
||||||
// registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are
|
// registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are
|
||||||
// unregistered or ambigious. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know
|
// unregistered or ambiguous. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know
|
||||||
// the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot.
|
// the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot.
|
||||||
QueryExecModeExec
|
QueryExecModeExec
|
||||||
|
|
||||||
// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments.
|
// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments.
|
||||||
// Queries are executed in a single round trip. Type mappings can be registered with
|
// Queries are executed in a single round trip. Type mappings can be registered with
|
||||||
// pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambigious.
|
// pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambiguous.
|
||||||
// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use
|
// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use
|
||||||
// a map[string]string directly as an argument. This mode cannot.
|
// a map[string]string directly as an argument. This mode cannot.
|
||||||
//
|
//
|
||||||
@ -815,7 +843,7 @@ func (c *Conn) getStatementDescription(
|
|||||||
}
|
}
|
||||||
sd = c.statementCache.Get(sql)
|
sd = c.statementCache.Get(sql)
|
||||||
if sd == nil {
|
if sd == nil {
|
||||||
sd, err = c.Prepare(ctx, stmtcache.NextStatementName(), sql)
|
sd, err = c.Prepare(ctx, stmtcache.StatementName(sql), sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -994,7 +1022,7 @@ func (c *Conn) sendBatchQueryExecModeCacheStatement(ctx context.Context, b *Batc
|
|||||||
bi.sd = distinctNewQueries[idx]
|
bi.sd = distinctNewQueries[idx]
|
||||||
} else {
|
} else {
|
||||||
sd = &pgconn.StatementDescription{
|
sd = &pgconn.StatementDescription{
|
||||||
Name: stmtcache.NextStatementName(),
|
Name: stmtcache.StatementName(bi.query),
|
||||||
SQL: bi.query,
|
SQL: bi.query,
|
||||||
}
|
}
|
||||||
distinctNewQueriesIdxMap[sd.SQL] = len(distinctNewQueries)
|
distinctNewQueriesIdxMap[sd.SQL] = len(distinctNewQueries)
|
||||||
@ -1062,7 +1090,7 @@ func (c *Conn) sendBatchQueryExecModeDescribeExec(ctx context.Context, b *Batch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, distinctNewQueries []*pgconn.StatementDescription, sdCache stmtcache.Cache) (pbr *pipelineBatchResults) {
|
func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, distinctNewQueries []*pgconn.StatementDescription, sdCache stmtcache.Cache) (pbr *pipelineBatchResults) {
|
||||||
pipeline := c.pgConn.StartPipeline(context.Background())
|
pipeline := c.pgConn.StartPipeline(ctx)
|
||||||
defer func() {
|
defer func() {
|
||||||
if pbr != nil && pbr.err != nil {
|
if pbr != nil && pbr.err != nil {
|
||||||
pipeline.Close()
|
pipeline.Close()
|
||||||
|
12
vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
generated
vendored
12
vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
generated
vendored
@ -34,7 +34,8 @@ func (c *LRUCache) Get(key string) *pgconn.StatementDescription {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache.
|
// Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache or
|
||||||
|
// sd.SQL has been invalidated and HandleInvalidated has not been called yet.
|
||||||
func (c *LRUCache) Put(sd *pgconn.StatementDescription) {
|
func (c *LRUCache) Put(sd *pgconn.StatementDescription) {
|
||||||
if sd.SQL == "" {
|
if sd.SQL == "" {
|
||||||
panic("cannot store statement description with empty SQL")
|
panic("cannot store statement description with empty SQL")
|
||||||
@ -44,6 +45,13 @@ func (c *LRUCache) Put(sd *pgconn.StatementDescription) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The statement may have been invalidated but not yet handled. Do not readd it to the cache.
|
||||||
|
for _, invalidSD := range c.invalidStmts {
|
||||||
|
if invalidSD.SQL == sd.SQL {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if c.l.Len() == c.cap {
|
if c.l.Len() == c.cap {
|
||||||
c.invalidateOldest()
|
c.invalidateOldest()
|
||||||
}
|
}
|
||||||
@ -73,6 +81,8 @@ func (c *LRUCache) InvalidateAll() {
|
|||||||
c.l = list.New()
|
c.l = list.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleInvalidated returns a slice of all statement descriptions invalidated since the last call to HandleInvalidated.
|
||||||
|
// Typically, the caller will then deallocate them.
|
||||||
func (c *LRUCache) HandleInvalidated() []*pgconn.StatementDescription {
|
func (c *LRUCache) HandleInvalidated() []*pgconn.StatementDescription {
|
||||||
invalidStmts := c.invalidStmts
|
invalidStmts := c.invalidStmts
|
||||||
c.invalidStmts = nil
|
c.invalidStmts = nil
|
||||||
|
31
vendor/github.com/jackc/pgx/v5/internal/stmtcache/stmtcache.go
generated
vendored
31
vendor/github.com/jackc/pgx/v5/internal/stmtcache/stmtcache.go
generated
vendored
@ -2,18 +2,17 @@
|
|||||||
package stmtcache
|
package stmtcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"crypto/sha256"
|
||||||
"sync/atomic"
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stmtCounter int64
|
// StatementName returns a statement name that will be stable for sql across multiple connections and program
|
||||||
|
// executions.
|
||||||
// NextStatementName returns a statement name that will be unique for the lifetime of the program.
|
func StatementName(sql string) string {
|
||||||
func NextStatementName() string {
|
digest := sha256.Sum256([]byte(sql))
|
||||||
n := atomic.AddInt64(&stmtCounter, 1)
|
return "stmtcache_" + hex.EncodeToString(digest[0:24])
|
||||||
return "stmtcache_" + strconv.FormatInt(n, 10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache caches statement descriptions.
|
// Cache caches statement descriptions.
|
||||||
@ -39,19 +38,3 @@ type Cache interface {
|
|||||||
// Cap returns the maximum number of cached prepared statement descriptions.
|
// Cap returns the maximum number of cached prepared statement descriptions.
|
||||||
Cap() int
|
Cap() int
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsStatementInvalid(err error) bool {
|
|
||||||
pgErr, ok := err.(*pgconn.PgError)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/jackc/pgx/issues/1162
|
|
||||||
//
|
|
||||||
// We used to look for the message "cached plan must not change result type". However, that message can be localized.
|
|
||||||
// Unfortunately, error code "0A000" - "FEATURE NOT SUPPORTED" is used for many different errors and the only way to
|
|
||||||
// tell the difference is by the message. But all that happens is we clear a statement that we otherwise wouldn't
|
|
||||||
// have so it should be safe.
|
|
||||||
possibleInvalidCachedPlanError := pgErr.Code == "0A000"
|
|
||||||
return possibleInvalidCachedPlanError
|
|
||||||
}
|
|
||||||
|
4
vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
generated
vendored
4
vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
generated
vendored
@ -47,7 +47,7 @@ func (c *PgConn) scramAuth(serverAuthMechanisms []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive server-first-message payload in a AuthenticationSASLContinue.
|
// Receive server-first-message payload in an AuthenticationSASLContinue.
|
||||||
saslContinue, err := c.rxSASLContinue()
|
saslContinue, err := c.rxSASLContinue()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -67,7 +67,7 @@ func (c *PgConn) scramAuth(serverAuthMechanisms []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive server-final-message payload in a AuthenticationSASLFinal.
|
// Receive server-final-message payload in an AuthenticationSASLFinal.
|
||||||
saslFinal, err := c.rxSASLFinal()
|
saslFinal, err := c.rxSASLFinal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
10
vendor/github.com/jackc/pgx/v5/pgconn/config.go
generated
vendored
10
vendor/github.com/jackc/pgx/v5/pgconn/config.go
generated
vendored
@ -809,7 +809,7 @@ func makeConnectTimeoutDialFunc(timeout time.Duration) DialFunc {
|
|||||||
return d.DialContext
|
return d.DialContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConnectTargetSessionAttrsReadWrite is an ValidateConnectFunc that implements libpq compatible
|
// ValidateConnectTargetSessionAttrsReadWrite is a ValidateConnectFunc that implements libpq compatible
|
||||||
// target_session_attrs=read-write.
|
// target_session_attrs=read-write.
|
||||||
func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error {
|
func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error {
|
||||||
result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
|
result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
|
||||||
@ -824,7 +824,7 @@ func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgC
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConnectTargetSessionAttrsReadOnly is an ValidateConnectFunc that implements libpq compatible
|
// ValidateConnectTargetSessionAttrsReadOnly is a ValidateConnectFunc that implements libpq compatible
|
||||||
// target_session_attrs=read-only.
|
// target_session_attrs=read-only.
|
||||||
func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error {
|
func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error {
|
||||||
result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
|
result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
|
||||||
@ -839,7 +839,7 @@ func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgCo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConnectTargetSessionAttrsStandby is an ValidateConnectFunc that implements libpq compatible
|
// ValidateConnectTargetSessionAttrsStandby is a ValidateConnectFunc that implements libpq compatible
|
||||||
// target_session_attrs=standby.
|
// target_session_attrs=standby.
|
||||||
func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error {
|
func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error {
|
||||||
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
||||||
@ -854,7 +854,7 @@ func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgCon
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConnectTargetSessionAttrsPrimary is an ValidateConnectFunc that implements libpq compatible
|
// ValidateConnectTargetSessionAttrsPrimary is a ValidateConnectFunc that implements libpq compatible
|
||||||
// target_session_attrs=primary.
|
// target_session_attrs=primary.
|
||||||
func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error {
|
func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error {
|
||||||
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
||||||
@ -869,7 +869,7 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConnectTargetSessionAttrsPreferStandby is an ValidateConnectFunc that implements libpq compatible
|
// ValidateConnectTargetSessionAttrsPreferStandby is a ValidateConnectFunc that implements libpq compatible
|
||||||
// target_session_attrs=prefer-standby.
|
// target_session_attrs=prefer-standby.
|
||||||
func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
|
func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
|
||||||
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
||||||
|
57
vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
generated
vendored
57
vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
generated
vendored
@ -74,6 +74,7 @@ type PgConn struct {
|
|||||||
frontend *pgproto3.Frontend
|
frontend *pgproto3.Frontend
|
||||||
bgReader *bgreader.BGReader
|
bgReader *bgreader.BGReader
|
||||||
slowWriteTimer *time.Timer
|
slowWriteTimer *time.Timer
|
||||||
|
bgReaderStarted chan struct{}
|
||||||
|
|
||||||
config *Config
|
config *Config
|
||||||
|
|
||||||
@ -301,8 +302,14 @@ func connect(ctx context.Context, config *Config, fallbackConfig *FallbackConfig
|
|||||||
pgConn.parameterStatuses = make(map[string]string)
|
pgConn.parameterStatuses = make(map[string]string)
|
||||||
pgConn.status = connStatusConnecting
|
pgConn.status = connStatusConnecting
|
||||||
pgConn.bgReader = bgreader.New(pgConn.conn)
|
pgConn.bgReader = bgreader.New(pgConn.conn)
|
||||||
pgConn.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64), pgConn.bgReader.Start)
|
pgConn.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64),
|
||||||
|
func() {
|
||||||
|
pgConn.bgReader.Start()
|
||||||
|
pgConn.bgReaderStarted <- struct{}{}
|
||||||
|
},
|
||||||
|
)
|
||||||
pgConn.slowWriteTimer.Stop()
|
pgConn.slowWriteTimer.Stop()
|
||||||
|
pgConn.bgReaderStarted = make(chan struct{})
|
||||||
pgConn.frontend = config.BuildFrontend(pgConn.bgReader, pgConn.conn)
|
pgConn.frontend = config.BuildFrontend(pgConn.bgReader, pgConn.conn)
|
||||||
|
|
||||||
startupMsg := pgproto3.StartupMessage{
|
startupMsg := pgproto3.StartupMessage{
|
||||||
@ -593,7 +600,7 @@ func (pgConn *PgConn) Frontend() *pgproto3.Frontend {
|
|||||||
return pgConn.frontend
|
return pgConn.frontend
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes a connection. It is safe to call Close on a already closed connection. Close attempts a clean close by
|
// Close closes a connection. It is safe to call Close on an already closed connection. Close attempts a clean close by
|
||||||
// sending the exit message to PostgreSQL. However, this could block so ctx is available to limit the time to wait. The
|
// sending the exit message to PostgreSQL. However, this could block so ctx is available to limit the time to wait. The
|
||||||
// underlying net.Conn.Close() will always be called regardless of any other errors.
|
// underlying net.Conn.Close() will always be called regardless of any other errors.
|
||||||
func (pgConn *PgConn) Close(ctx context.Context) error {
|
func (pgConn *PgConn) Close(ctx context.Context) error {
|
||||||
@ -935,16 +942,21 @@ func (pgConn *PgConn) CancelRequest(ctx context.Context) error {
|
|||||||
buf := make([]byte, 16)
|
buf := make([]byte, 16)
|
||||||
binary.BigEndian.PutUint32(buf[0:4], 16)
|
binary.BigEndian.PutUint32(buf[0:4], 16)
|
||||||
binary.BigEndian.PutUint32(buf[4:8], 80877102)
|
binary.BigEndian.PutUint32(buf[4:8], 80877102)
|
||||||
binary.BigEndian.PutUint32(buf[8:12], uint32(pgConn.pid))
|
binary.BigEndian.PutUint32(buf[8:12], pgConn.pid)
|
||||||
binary.BigEndian.PutUint32(buf[12:16], uint32(pgConn.secretKey))
|
binary.BigEndian.PutUint32(buf[12:16], pgConn.secretKey)
|
||||||
// Postgres will process the request and close the connection
|
|
||||||
// so when don't need to read the reply
|
if _, err := cancelConn.Write(buf); err != nil {
|
||||||
// https://www.postgresql.org/docs/current/protocol-flow.html#id-1.10.6.7.10
|
return fmt.Errorf("write to connection for cancellation: %w", err)
|
||||||
_, err = cancelConn.Write(buf)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForNotification waits for a LISTON/NOTIFY message to be received. It returns an error if a notification was not
|
// Wait for the cancel request to be acknowledged by the server.
|
||||||
|
// It copies the behavior of the libpq: https://github.com/postgres/postgres/blob/REL_16_0/src/interfaces/libpq/fe-connect.c#L4946-L4960
|
||||||
|
_, _ = cancelConn.Read(buf)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitForNotification waits for a LISTEN/NOTIFY message to be received. It returns an error if a notification was not
|
||||||
// received.
|
// received.
|
||||||
func (pgConn *PgConn) WaitForNotification(ctx context.Context) error {
|
func (pgConn *PgConn) WaitForNotification(ctx context.Context) error {
|
||||||
if err := pgConn.lock(); err != nil {
|
if err := pgConn.lock(); err != nil {
|
||||||
@ -1732,11 +1744,17 @@ func (pgConn *PgConn) enterPotentialWriteReadDeadlock() {
|
|||||||
|
|
||||||
// exitPotentialWriteReadDeadlock must be called after a call to enterPotentialWriteReadDeadlock.
|
// exitPotentialWriteReadDeadlock must be called after a call to enterPotentialWriteReadDeadlock.
|
||||||
func (pgConn *PgConn) exitPotentialWriteReadDeadlock() {
|
func (pgConn *PgConn) exitPotentialWriteReadDeadlock() {
|
||||||
// The state of the timer is not relevant upon exiting the potential slow write. It may both
|
if !pgConn.slowWriteTimer.Stop() {
|
||||||
// fire (due to a slow write), or not fire (due to a fast write).
|
// The timer starts its function in a separate goroutine. It is necessary to ensure the background reader has
|
||||||
_ = pgConn.slowWriteTimer.Stop()
|
// started before calling Stop. Otherwise, the background reader may not be stopped. That on its own is not a
|
||||||
|
// serious problem. But what is a serious problem is that the background reader may start at an inopportune time in
|
||||||
|
// a subsequent query. For example, if a subsequent query was canceled then a deadline may be set on the net.Conn to
|
||||||
|
// interrupt an in-progress read. After the read is interrupted, but before the deadline is cleared, the background
|
||||||
|
// reader could start and read a deadline error. Then the next query would receive the an unexpected deadline error.
|
||||||
|
<-pgConn.bgReaderStarted
|
||||||
pgConn.bgReader.Stop()
|
pgConn.bgReader.Stop()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (pgConn *PgConn) flushWithPotentialWriteReadDeadlock() error {
|
func (pgConn *PgConn) flushWithPotentialWriteReadDeadlock() error {
|
||||||
pgConn.enterPotentialWriteReadDeadlock()
|
pgConn.enterPotentialWriteReadDeadlock()
|
||||||
@ -1764,7 +1782,7 @@ func (pgConn *PgConn) SyncConn(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should never happen. Only way I can imagine this occuring is if the server is constantly sending data such as
|
// This should never happen. Only way I can imagine this occurring is if the server is constantly sending data such as
|
||||||
// LISTEN/NOTIFY or log notifications such that we never can get an empty buffer.
|
// LISTEN/NOTIFY or log notifications such that we never can get an empty buffer.
|
||||||
return errors.New("SyncConn: conn never synchronized")
|
return errors.New("SyncConn: conn never synchronized")
|
||||||
}
|
}
|
||||||
@ -1830,8 +1848,14 @@ func Construct(hc *HijackedConn) (*PgConn, error) {
|
|||||||
|
|
||||||
pgConn.contextWatcher = newContextWatcher(pgConn.conn)
|
pgConn.contextWatcher = newContextWatcher(pgConn.conn)
|
||||||
pgConn.bgReader = bgreader.New(pgConn.conn)
|
pgConn.bgReader = bgreader.New(pgConn.conn)
|
||||||
pgConn.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64), pgConn.bgReader.Start)
|
pgConn.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64),
|
||||||
|
func() {
|
||||||
|
pgConn.bgReader.Start()
|
||||||
|
pgConn.bgReaderStarted <- struct{}{}
|
||||||
|
},
|
||||||
|
)
|
||||||
pgConn.slowWriteTimer.Stop()
|
pgConn.slowWriteTimer.Stop()
|
||||||
|
pgConn.bgReaderStarted = make(chan struct{})
|
||||||
pgConn.frontend = hc.Config.BuildFrontend(pgConn.bgReader, pgConn.conn)
|
pgConn.frontend = hc.Config.BuildFrontend(pgConn.bgReader, pgConn.conn)
|
||||||
|
|
||||||
return pgConn, nil
|
return pgConn, nil
|
||||||
@ -1996,7 +2020,8 @@ func (p *Pipeline) GetResults() (results any, err error) {
|
|||||||
for {
|
for {
|
||||||
msg, err := p.conn.receiveMessage()
|
msg, err := p.conn.receiveMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
p.conn.asyncClose()
|
||||||
|
return nil, normalizeTimeoutError(p.ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
|
2
vendor/github.com/jackc/pgx/v5/pgproto3/README.md
generated
vendored
2
vendor/github.com/jackc/pgx/v5/pgproto3/README.md
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
# pgproto3
|
# pgproto3
|
||||||
|
|
||||||
Package pgproto3 is a encoder and decoder of the PostgreSQL wire protocol version 3.
|
Package pgproto3 is an encoder and decoder of the PostgreSQL wire protocol version 3.
|
||||||
|
|
||||||
pgproto3 can be used as a foundation for PostgreSQL drivers, proxies, mock servers, load balancers and more.
|
pgproto3 can be used as a foundation for PostgreSQL drivers, proxies, mock servers, load balancers and more.
|
||||||
|
|
||||||
|
4
vendor/github.com/jackc/pgx/v5/pgproto3/doc.go
generated
vendored
4
vendor/github.com/jackc/pgx/v5/pgproto3/doc.go
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
// Package pgproto3 is a encoder and decoder of the PostgreSQL wire protocol version 3.
|
// Package pgproto3 is an encoder and decoder of the PostgreSQL wire protocol version 3.
|
||||||
//
|
//
|
||||||
// The primary interfaces are Frontend and Backend. They correspond to a client and server respectively. Messages are
|
// The primary interfaces are Frontend and Backend. They correspond to a client and server respectively. Messages are
|
||||||
// sent with Send (or a specialized Send variant). Messages are automatically bufferred to minimize small writes. Call
|
// sent with Send (or a specialized Send variant). Messages are automatically buffered to minimize small writes. Call
|
||||||
// Flush to ensure a message has actually been sent.
|
// Flush to ensure a message has actually been sent.
|
||||||
//
|
//
|
||||||
// The Trace method of Frontend and Backend can be used to examine the wire-level message traffic. It outputs in a
|
// The Trace method of Frontend and Backend can be used to examine the wire-level message traffic. It outputs in a
|
||||||
|
2
vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
generated
vendored
2
vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
generated
vendored
@ -156,7 +156,7 @@ func (f *Frontend) SendDescribe(msg *Describe) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendExecute sends a Execute message to the backend (i.e. the server). The message is not guaranteed to be written until
|
// SendExecute sends an Execute message to the backend (i.e. the server). The message is not guaranteed to be written until
|
||||||
// Flush is called.
|
// Flush is called.
|
||||||
func (f *Frontend) SendExecute(msg *Execute) {
|
func (f *Frontend) SendExecute(msg *Execute) {
|
||||||
prevLen := len(f.wbuf)
|
prevLen := len(f.wbuf)
|
||||||
|
4
vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go
generated
vendored
4
vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go
generated
vendored
@ -38,14 +38,14 @@ func (dst *StartupMessage) Decode(src []byte) error {
|
|||||||
for {
|
for {
|
||||||
idx := bytes.IndexByte(src[rp:], 0)
|
idx := bytes.IndexByte(src[rp:], 0)
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
return &invalidMessageFormatErr{messageType: "StartupMesage"}
|
return &invalidMessageFormatErr{messageType: "StartupMessage"}
|
||||||
}
|
}
|
||||||
key := string(src[rp : rp+idx])
|
key := string(src[rp : rp+idx])
|
||||||
rp += idx + 1
|
rp += idx + 1
|
||||||
|
|
||||||
idx = bytes.IndexByte(src[rp:], 0)
|
idx = bytes.IndexByte(src[rp:], 0)
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
return &invalidMessageFormatErr{messageType: "StartupMesage"}
|
return &invalidMessageFormatErr{messageType: "StartupMessage"}
|
||||||
}
|
}
|
||||||
value := string(src[rp : rp+idx])
|
value := string(src[rp : rp+idx])
|
||||||
rp += idx + 1
|
rp += idx + 1
|
||||||
|
4
vendor/github.com/jackc/pgx/v5/pgtype/doc.go
generated
vendored
4
vendor/github.com/jackc/pgx/v5/pgtype/doc.go
generated
vendored
@ -67,7 +67,7 @@ See example_custom_type_test.go for an example of a custom type for the PostgreS
|
|||||||
|
|
||||||
Sometimes pgx supports a PostgreSQL type such as numeric but the Go type is in an external package that does not have
|
Sometimes pgx supports a PostgreSQL type such as numeric but the Go type is in an external package that does not have
|
||||||
pgx support such as github.com/shopspring/decimal. These types can be registered with pgtype with custom conversion
|
pgx support such as github.com/shopspring/decimal. These types can be registered with pgtype with custom conversion
|
||||||
logic. See https://github.com/jackc/pgx-shopspring-decimal and https://github.com/jackc/pgx-gofrs-uuid for a example
|
logic. See https://github.com/jackc/pgx-shopspring-decimal and https://github.com/jackc/pgx-gofrs-uuid for example
|
||||||
integrations.
|
integrations.
|
||||||
|
|
||||||
New PostgreSQL Type Support
|
New PostgreSQL Type Support
|
||||||
@ -149,7 +149,7 @@ Overview of Scanning Implementation
|
|||||||
The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID
|
The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID
|
||||||
from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for
|
from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for
|
||||||
scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are
|
scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are
|
||||||
interfaces rather than explicit types. For example, PointCodec can use any Go type that implments the PointScanner and
|
interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner and
|
||||||
PointValuer interfaces.
|
PointValuer interfaces.
|
||||||
|
|
||||||
If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again.
|
If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again.
|
||||||
|
24
vendor/github.com/jackc/pgx/v5/pgtype/float4.go
generated
vendored
24
vendor/github.com/jackc/pgx/v5/pgtype/float4.go
generated
vendored
@ -3,6 +3,7 @@ package pgtype
|
|||||||
import (
|
import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -65,6 +66,29 @@ func (f Float4) Value() (driver.Value, error) {
|
|||||||
return float64(f.Float32), nil
|
return float64(f.Float32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f Float4) MarshalJSON() ([]byte, error) {
|
||||||
|
if !f.Valid {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
return json.Marshal(f.Float32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Float4) UnmarshalJSON(b []byte) error {
|
||||||
|
var n *float32
|
||||||
|
err := json.Unmarshal(b, &n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == nil {
|
||||||
|
*f = Float4{}
|
||||||
|
} else {
|
||||||
|
*f = Float4{Float32: *n, Valid: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Float4Codec struct{}
|
type Float4Codec struct{}
|
||||||
|
|
||||||
func (Float4Codec) FormatSupported(format int16) bool {
|
func (Float4Codec) FormatSupported(format int16) bool {
|
||||||
|
30
vendor/github.com/jackc/pgx/v5/pgtype/float8.go
generated
vendored
30
vendor/github.com/jackc/pgx/v5/pgtype/float8.go
generated
vendored
@ -74,6 +74,29 @@ func (f Float8) Value() (driver.Value, error) {
|
|||||||
return f.Float64, nil
|
return f.Float64, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f Float8) MarshalJSON() ([]byte, error) {
|
||||||
|
if !f.Valid {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
return json.Marshal(f.Float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Float8) UnmarshalJSON(b []byte) error {
|
||||||
|
var n *float64
|
||||||
|
err := json.Unmarshal(b, &n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == nil {
|
||||||
|
*f = Float8{}
|
||||||
|
} else {
|
||||||
|
*f = Float8{Float64: *n, Valid: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Float8Codec struct{}
|
type Float8Codec struct{}
|
||||||
|
|
||||||
func (Float8Codec) FormatSupported(format int16) bool {
|
func (Float8Codec) FormatSupported(format int16) bool {
|
||||||
@ -109,13 +132,6 @@ func (Float8Codec) PlanEncode(m *Map, oid uint32, format int16, value any) Encod
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Float8) MarshalJSON() ([]byte, error) {
|
|
||||||
if !f.Valid {
|
|
||||||
return []byte("null"), nil
|
|
||||||
}
|
|
||||||
return json.Marshal(f.Float64)
|
|
||||||
}
|
|
||||||
|
|
||||||
type encodePlanFloat8CodecBinaryFloat64 struct{}
|
type encodePlanFloat8CodecBinaryFloat64 struct{}
|
||||||
|
|
||||||
func (encodePlanFloat8CodecBinaryFloat64) Encode(value any, buf []byte) (newBuf []byte, err error) {
|
func (encodePlanFloat8CodecBinaryFloat64) Encode(value any, buf []byte) (newBuf []byte, err error) {
|
||||||
|
2
vendor/github.com/jackc/pgx/v5/pgtype/inet.go
generated
vendored
2
vendor/github.com/jackc/pgx/v5/pgtype/inet.go
generated
vendored
@ -156,7 +156,7 @@ func (scanPlanBinaryInetToNetipPrefixScanner) Scan(src []byte, dst any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(src) != 8 && len(src) != 20 {
|
if len(src) != 8 && len(src) != 20 {
|
||||||
return fmt.Errorf("Received an invalid size for a inet: %d", len(src))
|
return fmt.Errorf("Received an invalid size for an inet: %d", len(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore family
|
// ignore family
|
||||||
|
16
vendor/github.com/jackc/pgx/v5/pgtype/interval.go
generated
vendored
16
vendor/github.com/jackc/pgx/v5/pgtype/interval.go
generated
vendored
@ -179,7 +179,7 @@ func (scanPlanBinaryIntervalToIntervalScanner) Scan(src []byte, dst any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(src) != 16 {
|
if len(src) != 16 {
|
||||||
return fmt.Errorf("Received an invalid size for a interval: %d", len(src))
|
return fmt.Errorf("Received an invalid size for an interval: %d", len(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
microseconds := int64(binary.BigEndian.Uint64(src))
|
microseconds := int64(binary.BigEndian.Uint64(src))
|
||||||
@ -242,21 +242,21 @@ func (scanPlanTextAnyToIntervalScanner) Scan(src []byte, dst any) error {
|
|||||||
return fmt.Errorf("bad interval minute format: %s", timeParts[1])
|
return fmt.Errorf("bad interval minute format: %s", timeParts[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
secondParts := strings.SplitN(timeParts[2], ".", 2)
|
sec, secFrac, secFracFound := strings.Cut(timeParts[2], ".")
|
||||||
|
|
||||||
seconds, err := strconv.ParseInt(secondParts[0], 10, 64)
|
seconds, err := strconv.ParseInt(sec, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("bad interval second format: %s", secondParts[0])
|
return fmt.Errorf("bad interval second format: %s", sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uSeconds int64
|
var uSeconds int64
|
||||||
if len(secondParts) == 2 {
|
if secFracFound {
|
||||||
uSeconds, err = strconv.ParseInt(secondParts[1], 10, 64)
|
uSeconds, err = strconv.ParseInt(secFrac, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("bad interval decimal format: %s", secondParts[1])
|
return fmt.Errorf("bad interval decimal format: %s", secFrac)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 6-len(secondParts[1]); i++ {
|
for i := 0; i < 6-len(secFrac); i++ {
|
||||||
uSeconds *= 10
|
uSeconds *= 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
generated
vendored
15
vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
generated
vendored
@ -1358,6 +1358,8 @@ var kindToTypes map[reflect.Kind]reflect.Type = map[reflect.Kind]reflect.Type{
|
|||||||
reflect.Bool: reflect.TypeOf(false),
|
reflect.Bool: reflect.TypeOf(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var byteSliceType = reflect.TypeOf([]byte{})
|
||||||
|
|
||||||
type underlyingTypeEncodePlan struct {
|
type underlyingTypeEncodePlan struct {
|
||||||
nextValueType reflect.Type
|
nextValueType reflect.Type
|
||||||
next EncodePlan
|
next EncodePlan
|
||||||
@ -1372,6 +1374,10 @@ func (plan *underlyingTypeEncodePlan) Encode(value any, buf []byte) (newBuf []by
|
|||||||
// TryWrapFindUnderlyingTypeEncodePlan tries to convert to a Go builtin type. e.g. If value was of type MyString and
|
// TryWrapFindUnderlyingTypeEncodePlan tries to convert to a Go builtin type. e.g. If value was of type MyString and
|
||||||
// MyString was defined as a string then a wrapper plan would be returned that converts MyString to string.
|
// MyString was defined as a string then a wrapper plan would be returned that converts MyString to string.
|
||||||
func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool) {
|
func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool) {
|
||||||
|
if value == nil {
|
||||||
|
return nil, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := value.(driver.Valuer); ok {
|
if _, ok := value.(driver.Valuer); ok {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
@ -1387,6 +1393,15 @@ func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextS
|
|||||||
return &underlyingTypeEncodePlan{nextValueType: nextValueType}, refValue.Convert(nextValueType).Interface(), true
|
return &underlyingTypeEncodePlan{nextValueType: nextValueType}, refValue.Convert(nextValueType).Interface(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// []byte is a special case. It is a slice but we treat it as a scalar type. In the case of a named type like
|
||||||
|
// json.RawMessage which is defined as []byte the underlying type should be considered as []byte. But any other slice
|
||||||
|
// does not have a special underlying type.
|
||||||
|
//
|
||||||
|
// https://github.com/jackc/pgx/issues/1763
|
||||||
|
if refValue.Type() != byteSliceType && refValue.Type().AssignableTo(byteSliceType) {
|
||||||
|
return &underlyingTypeEncodePlan{nextValueType: byteSliceType}, refValue.Convert(byteSliceType).Interface(), true
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
vendor/github.com/jackc/pgx/v5/pgtype/point.go
generated
vendored
16
vendor/github.com/jackc/pgx/v5/pgtype/point.go
generated
vendored
@ -50,17 +50,17 @@ func parsePoint(src []byte) (*Point, error) {
|
|||||||
if src[0] == '"' && src[len(src)-1] == '"' {
|
if src[0] == '"' && src[len(src)-1] == '"' {
|
||||||
src = src[1 : len(src)-1]
|
src = src[1 : len(src)-1]
|
||||||
}
|
}
|
||||||
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
|
sx, sy, found := strings.Cut(string(src[1:len(src)-1]), ",")
|
||||||
if len(parts) < 2 {
|
if !found {
|
||||||
return nil, fmt.Errorf("invalid format for point")
|
return nil, fmt.Errorf("invalid format for point")
|
||||||
}
|
}
|
||||||
|
|
||||||
x, err := strconv.ParseFloat(parts[0], 64)
|
x, err := strconv.ParseFloat(sx, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
y, err := strconv.ParseFloat(parts[1], 64)
|
y, err := strconv.ParseFloat(sy, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -247,17 +247,17 @@ func (scanPlanTextAnyToPointScanner) Scan(src []byte, dst any) error {
|
|||||||
return fmt.Errorf("invalid length for point: %v", len(src))
|
return fmt.Errorf("invalid length for point: %v", len(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
|
sx, sy, found := strings.Cut(string(src[1:len(src)-1]), ",")
|
||||||
if len(parts) < 2 {
|
if !found {
|
||||||
return fmt.Errorf("invalid format for point")
|
return fmt.Errorf("invalid format for point")
|
||||||
}
|
}
|
||||||
|
|
||||||
x, err := strconv.ParseFloat(parts[0], 64)
|
x, err := strconv.ParseFloat(sx, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
y, err := strconv.ParseFloat(parts[1], 64)
|
y, err := strconv.ParseFloat(sy, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/jackc/pgx/v5/pgtype/tid.go
generated
vendored
8
vendor/github.com/jackc/pgx/v5/pgtype/tid.go
generated
vendored
@ -205,17 +205,17 @@ func (scanPlanTextAnyToTIDScanner) Scan(src []byte, dst any) error {
|
|||||||
return fmt.Errorf("invalid length for tid: %v", len(src))
|
return fmt.Errorf("invalid length for tid: %v", len(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
|
block, offset, found := strings.Cut(string(src[1:len(src)-1]), ",")
|
||||||
if len(parts) < 2 {
|
if !found {
|
||||||
return fmt.Errorf("invalid format for tid")
|
return fmt.Errorf("invalid format for tid")
|
||||||
}
|
}
|
||||||
|
|
||||||
blockNumber, err := strconv.ParseUint(parts[0], 10, 32)
|
blockNumber, err := strconv.ParseUint(block, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetNumber, err := strconv.ParseUint(parts[1], 10, 16)
|
offsetNumber, err := strconv.ParseUint(offset, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
52
vendor/github.com/jackc/pgx/v5/pgxpool/batch_results.go
generated
vendored
Normal file
52
vendor/github.com/jackc/pgx/v5/pgxpool/batch_results.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errBatchResults struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br errBatchResults) Exec() (pgconn.CommandTag, error) {
|
||||||
|
return pgconn.CommandTag{}, br.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br errBatchResults) Query() (pgx.Rows, error) {
|
||||||
|
return errRows{err: br.err}, br.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br errBatchResults) QueryRow() pgx.Row {
|
||||||
|
return errRow{err: br.err}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br errBatchResults) Close() error {
|
||||||
|
return br.err
|
||||||
|
}
|
||||||
|
|
||||||
|
type poolBatchResults struct {
|
||||||
|
br pgx.BatchResults
|
||||||
|
c *Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *poolBatchResults) Exec() (pgconn.CommandTag, error) {
|
||||||
|
return br.br.Exec()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *poolBatchResults) Query() (pgx.Rows, error) {
|
||||||
|
return br.br.Query()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *poolBatchResults) QueryRow() pgx.Row {
|
||||||
|
return br.br.QueryRow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *poolBatchResults) Close() error {
|
||||||
|
err := br.br.Close()
|
||||||
|
if br.c != nil {
|
||||||
|
br.c.Release()
|
||||||
|
br.c = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
130
vendor/github.com/jackc/pgx/v5/pgxpool/conn.go
generated
vendored
Normal file
130
vendor/github.com/jackc/pgx/v5/pgxpool/conn.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
"github.com/jackc/puddle/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Conn is an acquired *pgx.Conn from a Pool.
|
||||||
|
type Conn struct {
|
||||||
|
res *puddle.Resource[*connResource]
|
||||||
|
p *Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release returns c to the pool it was acquired from. Once Release has been called, other methods must not be called.
|
||||||
|
// However, it is safe to call Release multiple times. Subsequent calls after the first will be ignored.
|
||||||
|
func (c *Conn) Release() {
|
||||||
|
if c.res == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := c.Conn()
|
||||||
|
res := c.res
|
||||||
|
c.res = nil
|
||||||
|
|
||||||
|
if conn.IsClosed() || conn.PgConn().IsBusy() || conn.PgConn().TxStatus() != 'I' {
|
||||||
|
res.Destroy()
|
||||||
|
// Signal to the health check to run since we just destroyed a connections
|
||||||
|
// and we might be below minConns now
|
||||||
|
c.p.triggerHealthCheck()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the pool is consistently being used, we might never get to check the
|
||||||
|
// lifetime of a connection since we only check idle connections in checkConnsHealth
|
||||||
|
// so we also check the lifetime here and force a health check
|
||||||
|
if c.p.isExpired(res) {
|
||||||
|
atomic.AddInt64(&c.p.lifetimeDestroyCount, 1)
|
||||||
|
res.Destroy()
|
||||||
|
// Signal to the health check to run since we just destroyed a connections
|
||||||
|
// and we might be below minConns now
|
||||||
|
c.p.triggerHealthCheck()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.p.afterRelease == nil {
|
||||||
|
res.Release()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if c.p.afterRelease(conn) {
|
||||||
|
res.Release()
|
||||||
|
} else {
|
||||||
|
res.Destroy()
|
||||||
|
// Signal to the health check to run since we just destroyed a connections
|
||||||
|
// and we might be below minConns now
|
||||||
|
c.p.triggerHealthCheck()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hijack assumes ownership of the connection from the pool. Caller is responsible for closing the connection. Hijack
|
||||||
|
// will panic if called on an already released or hijacked connection.
|
||||||
|
func (c *Conn) Hijack() *pgx.Conn {
|
||||||
|
if c.res == nil {
|
||||||
|
panic("cannot hijack already released or hijacked connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := c.Conn()
|
||||||
|
res := c.res
|
||||||
|
c.res = nil
|
||||||
|
|
||||||
|
res.Hijack()
|
||||||
|
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error) {
|
||||||
|
return c.Conn().Exec(ctx, sql, arguments...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) {
|
||||||
|
return c.Conn().Query(ctx, sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row {
|
||||||
|
return c.Conn().QueryRow(ctx, sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults {
|
||||||
|
return c.Conn().SendBatch(ctx, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) {
|
||||||
|
return c.Conn().CopyFrom(ctx, tableName, columnNames, rowSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin starts a transaction block from the *Conn without explicitly setting a transaction mode (see BeginTx with TxOptions if transaction mode is required).
|
||||||
|
func (c *Conn) Begin(ctx context.Context) (pgx.Tx, error) {
|
||||||
|
return c.Conn().Begin(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeginTx starts a transaction block from the *Conn with txOptions determining the transaction mode.
|
||||||
|
func (c *Conn) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) {
|
||||||
|
return c.Conn().BeginTx(ctx, txOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Ping(ctx context.Context) error {
|
||||||
|
return c.Conn().Ping(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Conn() *pgx.Conn {
|
||||||
|
return c.connResource().conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) connResource() *connResource {
|
||||||
|
return c.res.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) getPoolRow(r pgx.Row) *poolRow {
|
||||||
|
return c.connResource().getPoolRow(c, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) getPoolRows(r pgx.Rows) *poolRows {
|
||||||
|
return c.connResource().getPoolRows(c, r)
|
||||||
|
}
|
27
vendor/github.com/jackc/pgx/v5/pgxpool/doc.go
generated
vendored
Normal file
27
vendor/github.com/jackc/pgx/v5/pgxpool/doc.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Package pgxpool is a concurrency-safe connection pool for pgx.
|
||||||
|
/*
|
||||||
|
pgxpool implements a nearly identical interface to pgx connections.
|
||||||
|
|
||||||
|
Creating a Pool
|
||||||
|
|
||||||
|
The primary way of creating a pool is with [pgxpool.New]:
|
||||||
|
|
||||||
|
pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
|
||||||
|
|
||||||
|
The database connection string can be in URL or DSN format. PostgreSQL settings, pgx settings, and pool settings can be
|
||||||
|
specified here. In addition, a config struct can be created by [ParseConfig].
|
||||||
|
|
||||||
|
config, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL"))
|
||||||
|
if err != nil {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
config.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
|
||||||
|
// do something with every new connection
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := pgxpool.NewWithConfig(context.Background(), config)
|
||||||
|
|
||||||
|
A pool returns without waiting for any connections to be established. Acquire a connection immediately after creating
|
||||||
|
the pool to check if a connection can successfully be established.
|
||||||
|
*/
|
||||||
|
package pgxpool
|
695
vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
generated
vendored
Normal file
695
vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
generated
vendored
Normal file
@ -0,0 +1,695 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
"github.com/jackc/puddle/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultMaxConns = int32(4)
|
||||||
|
var defaultMinConns = int32(0)
|
||||||
|
var defaultMaxConnLifetime = time.Hour
|
||||||
|
var defaultMaxConnIdleTime = time.Minute * 30
|
||||||
|
var defaultHealthCheckPeriod = time.Minute
|
||||||
|
|
||||||
|
type connResource struct {
|
||||||
|
conn *pgx.Conn
|
||||||
|
conns []Conn
|
||||||
|
poolRows []poolRow
|
||||||
|
poolRowss []poolRows
|
||||||
|
maxAgeTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cr *connResource) getConn(p *Pool, res *puddle.Resource[*connResource]) *Conn {
|
||||||
|
if len(cr.conns) == 0 {
|
||||||
|
cr.conns = make([]Conn, 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &cr.conns[len(cr.conns)-1]
|
||||||
|
cr.conns = cr.conns[0 : len(cr.conns)-1]
|
||||||
|
|
||||||
|
c.res = res
|
||||||
|
c.p = p
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cr *connResource) getPoolRow(c *Conn, r pgx.Row) *poolRow {
|
||||||
|
if len(cr.poolRows) == 0 {
|
||||||
|
cr.poolRows = make([]poolRow, 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
pr := &cr.poolRows[len(cr.poolRows)-1]
|
||||||
|
cr.poolRows = cr.poolRows[0 : len(cr.poolRows)-1]
|
||||||
|
|
||||||
|
pr.c = c
|
||||||
|
pr.r = r
|
||||||
|
|
||||||
|
return pr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cr *connResource) getPoolRows(c *Conn, r pgx.Rows) *poolRows {
|
||||||
|
if len(cr.poolRowss) == 0 {
|
||||||
|
cr.poolRowss = make([]poolRows, 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
pr := &cr.poolRowss[len(cr.poolRowss)-1]
|
||||||
|
cr.poolRowss = cr.poolRowss[0 : len(cr.poolRowss)-1]
|
||||||
|
|
||||||
|
pr.c = c
|
||||||
|
pr.r = r
|
||||||
|
|
||||||
|
return pr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool allows for connection reuse.
|
||||||
|
type Pool struct {
|
||||||
|
// 64 bit fields accessed with atomics must be at beginning of struct to guarantee alignment for certain 32-bit
|
||||||
|
// architectures. See BUGS section of https://pkg.go.dev/sync/atomic and https://github.com/jackc/pgx/issues/1288.
|
||||||
|
newConnsCount int64
|
||||||
|
lifetimeDestroyCount int64
|
||||||
|
idleDestroyCount int64
|
||||||
|
|
||||||
|
p *puddle.Pool[*connResource]
|
||||||
|
config *Config
|
||||||
|
beforeConnect func(context.Context, *pgx.ConnConfig) error
|
||||||
|
afterConnect func(context.Context, *pgx.Conn) error
|
||||||
|
beforeAcquire func(context.Context, *pgx.Conn) bool
|
||||||
|
afterRelease func(*pgx.Conn) bool
|
||||||
|
beforeClose func(*pgx.Conn)
|
||||||
|
minConns int32
|
||||||
|
maxConns int32
|
||||||
|
maxConnLifetime time.Duration
|
||||||
|
maxConnLifetimeJitter time.Duration
|
||||||
|
maxConnIdleTime time.Duration
|
||||||
|
healthCheckPeriod time.Duration
|
||||||
|
|
||||||
|
healthCheckChan chan struct{}
|
||||||
|
|
||||||
|
closeOnce sync.Once
|
||||||
|
closeChan chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
|
||||||
|
// modified.
|
||||||
|
type Config struct {
|
||||||
|
ConnConfig *pgx.ConnConfig
|
||||||
|
|
||||||
|
// BeforeConnect is called before a new connection is made. It is passed a copy of the underlying pgx.ConnConfig and
|
||||||
|
// will not impact any existing open connections.
|
||||||
|
BeforeConnect func(context.Context, *pgx.ConnConfig) error
|
||||||
|
|
||||||
|
// AfterConnect is called after a connection is established, but before it is added to the pool.
|
||||||
|
AfterConnect func(context.Context, *pgx.Conn) error
|
||||||
|
|
||||||
|
// BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the
|
||||||
|
// acquisition or false to indicate that the connection should be destroyed and a different connection should be
|
||||||
|
// acquired.
|
||||||
|
BeforeAcquire func(context.Context, *pgx.Conn) bool
|
||||||
|
|
||||||
|
// AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to
|
||||||
|
// return the connection to the pool or false to destroy the connection.
|
||||||
|
AfterRelease func(*pgx.Conn) bool
|
||||||
|
|
||||||
|
// BeforeClose is called right before a connection is closed and removed from the pool.
|
||||||
|
BeforeClose func(*pgx.Conn)
|
||||||
|
|
||||||
|
// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
|
||||||
|
MaxConnLifetime time.Duration
|
||||||
|
|
||||||
|
// MaxConnLifetimeJitter is the duration after MaxConnLifetime to randomly decide to close a connection.
|
||||||
|
// This helps prevent all connections from being closed at the exact same time, starving the pool.
|
||||||
|
MaxConnLifetimeJitter time.Duration
|
||||||
|
|
||||||
|
// MaxConnIdleTime is the duration after which an idle connection will be automatically closed by the health check.
|
||||||
|
MaxConnIdleTime time.Duration
|
||||||
|
|
||||||
|
// MaxConns is the maximum size of the pool. The default is the greater of 4 or runtime.NumCPU().
|
||||||
|
MaxConns int32
|
||||||
|
|
||||||
|
// MinConns is the minimum size of the pool. After connection closes, the pool might dip below MinConns. A low
|
||||||
|
// number of MinConns might mean the pool is empty after MaxConnLifetime until the health check has a chance
|
||||||
|
// to create new connections.
|
||||||
|
MinConns int32
|
||||||
|
|
||||||
|
// HealthCheckPeriod is the duration between checks of the health of idle connections.
|
||||||
|
HealthCheckPeriod time.Duration
|
||||||
|
|
||||||
|
createdByParseConfig bool // Used to enforce created by ParseConfig rule.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the config that is safe to use and modify.
|
||||||
|
// The only exception is the tls.Config:
|
||||||
|
// according to the tls.Config docs it must not be modified after creation.
|
||||||
|
func (c *Config) Copy() *Config {
|
||||||
|
newConfig := new(Config)
|
||||||
|
*newConfig = *c
|
||||||
|
newConfig.ConnConfig = c.ConnConfig.Copy()
|
||||||
|
return newConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnString returns the connection string as parsed by pgxpool.ParseConfig into pgxpool.Config.
|
||||||
|
func (c *Config) ConnString() string { return c.ConnConfig.ConnString() }
|
||||||
|
|
||||||
|
// New creates a new Pool. See [ParseConfig] for information on connString format.
|
||||||
|
func New(ctx context.Context, connString string) (*Pool, error) {
|
||||||
|
config, err := ParseConfig(connString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewWithConfig(ctx, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithConfig creates a new Pool. config must have been created by [ParseConfig].
|
||||||
|
func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
|
||||||
|
// Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from
|
||||||
|
// zero values.
|
||||||
|
if !config.createdByParseConfig {
|
||||||
|
panic("config must be created by ParseConfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &Pool{
|
||||||
|
config: config,
|
||||||
|
beforeConnect: config.BeforeConnect,
|
||||||
|
afterConnect: config.AfterConnect,
|
||||||
|
beforeAcquire: config.BeforeAcquire,
|
||||||
|
afterRelease: config.AfterRelease,
|
||||||
|
beforeClose: config.BeforeClose,
|
||||||
|
minConns: config.MinConns,
|
||||||
|
maxConns: config.MaxConns,
|
||||||
|
maxConnLifetime: config.MaxConnLifetime,
|
||||||
|
maxConnLifetimeJitter: config.MaxConnLifetimeJitter,
|
||||||
|
maxConnIdleTime: config.MaxConnIdleTime,
|
||||||
|
healthCheckPeriod: config.HealthCheckPeriod,
|
||||||
|
healthCheckChan: make(chan struct{}, 1),
|
||||||
|
closeChan: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
p.p, err = puddle.NewPool(
|
||||||
|
&puddle.Config[*connResource]{
|
||||||
|
Constructor: func(ctx context.Context) (*connResource, error) {
|
||||||
|
atomic.AddInt64(&p.newConnsCount, 1)
|
||||||
|
connConfig := p.config.ConnConfig.Copy()
|
||||||
|
|
||||||
|
// Connection will continue in background even if Acquire is canceled. Ensure that a connect won't hang forever.
|
||||||
|
if connConfig.ConnectTimeout <= 0 {
|
||||||
|
connConfig.ConnectTimeout = 2 * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.beforeConnect != nil {
|
||||||
|
if err := p.beforeConnect(ctx, connConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := pgx.ConnectConfig(ctx, connConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.afterConnect != nil {
|
||||||
|
err = p.afterConnect(ctx, conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close(ctx)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jitterSecs := rand.Float64() * config.MaxConnLifetimeJitter.Seconds()
|
||||||
|
maxAgeTime := time.Now().Add(config.MaxConnLifetime).Add(time.Duration(jitterSecs) * time.Second)
|
||||||
|
|
||||||
|
cr := &connResource{
|
||||||
|
conn: conn,
|
||||||
|
conns: make([]Conn, 64),
|
||||||
|
poolRows: make([]poolRow, 64),
|
||||||
|
poolRowss: make([]poolRows, 64),
|
||||||
|
maxAgeTime: maxAgeTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cr, nil
|
||||||
|
},
|
||||||
|
Destructor: func(value *connResource) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
|
conn := value.conn
|
||||||
|
if p.beforeClose != nil {
|
||||||
|
p.beforeClose(conn)
|
||||||
|
}
|
||||||
|
conn.Close(ctx)
|
||||||
|
select {
|
||||||
|
case <-conn.PgConn().CleanupDone():
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
},
|
||||||
|
MaxSize: config.MaxConns,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
p.createIdleResources(ctx, int(p.minConns))
|
||||||
|
p.backgroundHealthCheck()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the
|
||||||
|
// addition of the following variables:
|
||||||
|
//
|
||||||
|
// - pool_max_conns: integer greater than 0
|
||||||
|
// - pool_min_conns: integer 0 or greater
|
||||||
|
// - pool_max_conn_lifetime: duration string
|
||||||
|
// - pool_max_conn_idle_time: duration string
|
||||||
|
// - pool_health_check_period: duration string
|
||||||
|
// - pool_max_conn_lifetime_jitter: duration string
|
||||||
|
//
|
||||||
|
// See Config for definitions of these arguments.
|
||||||
|
//
|
||||||
|
// # Example DSN
|
||||||
|
// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
|
||||||
|
//
|
||||||
|
// # Example URL
|
||||||
|
// postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
|
||||||
|
func ParseConfig(connString string) (*Config, error) {
|
||||||
|
connConfig, err := pgx.ParseConfig(connString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &Config{
|
||||||
|
ConnConfig: connConfig,
|
||||||
|
createdByParseConfig: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conns"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_max_conns")
|
||||||
|
n, err := strconv.ParseInt(s, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot parse pool_max_conns: %w", err)
|
||||||
|
}
|
||||||
|
if n < 1 {
|
||||||
|
return nil, fmt.Errorf("pool_max_conns too small: %d", n)
|
||||||
|
}
|
||||||
|
config.MaxConns = int32(n)
|
||||||
|
} else {
|
||||||
|
config.MaxConns = defaultMaxConns
|
||||||
|
if numCPU := int32(runtime.NumCPU()); numCPU > config.MaxConns {
|
||||||
|
config.MaxConns = numCPU
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_conns"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_min_conns")
|
||||||
|
n, err := strconv.ParseInt(s, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot parse pool_min_conns: %w", err)
|
||||||
|
}
|
||||||
|
config.MinConns = int32(n)
|
||||||
|
} else {
|
||||||
|
config.MinConns = defaultMinConns
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
|
||||||
|
d, err := time.ParseDuration(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid pool_max_conn_lifetime: %w", err)
|
||||||
|
}
|
||||||
|
config.MaxConnLifetime = d
|
||||||
|
} else {
|
||||||
|
config.MaxConnLifetime = defaultMaxConnLifetime
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_idle_time"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_max_conn_idle_time")
|
||||||
|
d, err := time.ParseDuration(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid pool_max_conn_idle_time: %w", err)
|
||||||
|
}
|
||||||
|
config.MaxConnIdleTime = d
|
||||||
|
} else {
|
||||||
|
config.MaxConnIdleTime = defaultMaxConnIdleTime
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_health_check_period"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_health_check_period")
|
||||||
|
d, err := time.ParseDuration(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid pool_health_check_period: %w", err)
|
||||||
|
}
|
||||||
|
config.HealthCheckPeriod = d
|
||||||
|
} else {
|
||||||
|
config.HealthCheckPeriod = defaultHealthCheckPeriod
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime_jitter"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
|
||||||
|
d, err := time.ParseDuration(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err)
|
||||||
|
}
|
||||||
|
config.MaxConnLifetimeJitter = d
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes all connections in the pool and rejects future Acquire calls. Blocks until all connections are returned
|
||||||
|
// to pool and closed.
|
||||||
|
func (p *Pool) Close() {
|
||||||
|
p.closeOnce.Do(func() {
|
||||||
|
close(p.closeChan)
|
||||||
|
p.p.Close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) isExpired(res *puddle.Resource[*connResource]) bool {
|
||||||
|
return time.Now().After(res.Value().maxAgeTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) triggerHealthCheck() {
|
||||||
|
go func() {
|
||||||
|
// Destroy is asynchronous so we give it time to actually remove itself from
|
||||||
|
// the pool otherwise we might try to check the pool size too soon
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
select {
|
||||||
|
case p.healthCheckChan <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) backgroundHealthCheck() {
|
||||||
|
ticker := time.NewTicker(p.healthCheckPeriod)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-p.closeChan:
|
||||||
|
return
|
||||||
|
case <-p.healthCheckChan:
|
||||||
|
p.checkHealth()
|
||||||
|
case <-ticker.C:
|
||||||
|
p.checkHealth()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) checkHealth() {
|
||||||
|
for {
|
||||||
|
// If checkMinConns failed we don't destroy any connections since we couldn't
|
||||||
|
// even get to minConns
|
||||||
|
if err := p.checkMinConns(); err != nil {
|
||||||
|
// Should we log this error somewhere?
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !p.checkConnsHealth() {
|
||||||
|
// Since we didn't destroy any connections we can stop looping
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Technically Destroy is asynchronous but 500ms should be enough for it to
|
||||||
|
// remove it from the underlying pool
|
||||||
|
select {
|
||||||
|
case <-p.closeChan:
|
||||||
|
return
|
||||||
|
case <-time.After(500 * time.Millisecond):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkConnsHealth will check all idle connections, destroy a connection if
|
||||||
|
// it's idle or too old, and returns true if any were destroyed
|
||||||
|
func (p *Pool) checkConnsHealth() bool {
|
||||||
|
var destroyed bool
|
||||||
|
totalConns := p.Stat().TotalConns()
|
||||||
|
resources := p.p.AcquireAllIdle()
|
||||||
|
for _, res := range resources {
|
||||||
|
// We're okay going under minConns if the lifetime is up
|
||||||
|
if p.isExpired(res) && totalConns >= p.minConns {
|
||||||
|
atomic.AddInt64(&p.lifetimeDestroyCount, 1)
|
||||||
|
res.Destroy()
|
||||||
|
destroyed = true
|
||||||
|
// Since Destroy is async we manually decrement totalConns.
|
||||||
|
totalConns--
|
||||||
|
} else if res.IdleDuration() > p.maxConnIdleTime && totalConns > p.minConns {
|
||||||
|
atomic.AddInt64(&p.idleDestroyCount, 1)
|
||||||
|
res.Destroy()
|
||||||
|
destroyed = true
|
||||||
|
// Since Destroy is async we manually decrement totalConns.
|
||||||
|
totalConns--
|
||||||
|
} else {
|
||||||
|
res.ReleaseUnused()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destroyed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) checkMinConns() error {
|
||||||
|
// TotalConns can include ones that are being destroyed but we should have
|
||||||
|
// sleep(500ms) around all of the destroys to help prevent that from throwing
|
||||||
|
// off this check
|
||||||
|
toCreate := p.minConns - p.Stat().TotalConns()
|
||||||
|
if toCreate > 0 {
|
||||||
|
return p.createIdleResources(context.Background(), int(toCreate))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) createIdleResources(parentCtx context.Context, targetResources int) error {
|
||||||
|
ctx, cancel := context.WithCancel(parentCtx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
errs := make(chan error, targetResources)
|
||||||
|
|
||||||
|
for i := 0; i < targetResources; i++ {
|
||||||
|
go func() {
|
||||||
|
err := p.p.CreateResource(ctx)
|
||||||
|
// Ignore ErrNotAvailable since it means that the pool has become full since we started creating resource.
|
||||||
|
if err == puddle.ErrNotAvailable {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
errs <- err
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstError error
|
||||||
|
for i := 0; i < targetResources; i++ {
|
||||||
|
err := <-errs
|
||||||
|
if err != nil && firstError == nil {
|
||||||
|
cancel()
|
||||||
|
firstError = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire returns a connection (*Conn) from the Pool
|
||||||
|
func (p *Pool) Acquire(ctx context.Context) (*Conn, error) {
|
||||||
|
for {
|
||||||
|
res, err := p.p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cr := res.Value()
|
||||||
|
|
||||||
|
if res.IdleDuration() > time.Second {
|
||||||
|
err := cr.conn.Ping(ctx)
|
||||||
|
if err != nil {
|
||||||
|
res.Destroy()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
|
||||||
|
return cr.getConn(p, res), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the
|
||||||
|
// call of f. The return value is either an error acquiring the *Conn or the return value of f. The *Conn is
|
||||||
|
// automatically released after the call of f.
|
||||||
|
func (p *Pool) AcquireFunc(ctx context.Context, f func(*Conn) error) error {
|
||||||
|
conn, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Release()
|
||||||
|
|
||||||
|
return f(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireAllIdle atomically acquires all currently idle connections. Its intended use is for health check and
|
||||||
|
// keep-alive functionality. It does not update pool statistics.
|
||||||
|
func (p *Pool) AcquireAllIdle(ctx context.Context) []*Conn {
|
||||||
|
resources := p.p.AcquireAllIdle()
|
||||||
|
conns := make([]*Conn, 0, len(resources))
|
||||||
|
for _, res := range resources {
|
||||||
|
cr := res.Value()
|
||||||
|
if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
|
||||||
|
conns = append(conns, cr.getConn(p, res))
|
||||||
|
} else {
|
||||||
|
res.Destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset closes all connections, but leaves the pool open. It is intended for use when an error is detected that would
|
||||||
|
// disrupt all connections (such as a network interruption or a server state change).
|
||||||
|
//
|
||||||
|
// It is safe to reset a pool while connections are checked out. Those connections will be closed when they are returned
|
||||||
|
// to the pool.
|
||||||
|
func (p *Pool) Reset() {
|
||||||
|
p.p.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config returns a copy of config that was used to initialize this pool.
|
||||||
|
func (p *Pool) Config() *Config { return p.config.Copy() }
|
||||||
|
|
||||||
|
// Stat returns a pgxpool.Stat struct with a snapshot of Pool statistics.
|
||||||
|
func (p *Pool) Stat() *Stat {
|
||||||
|
return &Stat{
|
||||||
|
s: p.p.Stat(),
|
||||||
|
newConnsCount: atomic.LoadInt64(&p.newConnsCount),
|
||||||
|
lifetimeDestroyCount: atomic.LoadInt64(&p.lifetimeDestroyCount),
|
||||||
|
idleDestroyCount: atomic.LoadInt64(&p.idleDestroyCount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exec acquires a connection from the Pool and executes the given SQL.
|
||||||
|
// SQL can be either a prepared statement name or an SQL string.
|
||||||
|
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
|
||||||
|
// The acquired connection is returned to the pool when the Exec function returns.
|
||||||
|
func (p *Pool) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error) {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return pgconn.CommandTag{}, err
|
||||||
|
}
|
||||||
|
defer c.Release()
|
||||||
|
|
||||||
|
return c.Exec(ctx, sql, arguments...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query acquires a connection and executes a query that returns pgx.Rows.
|
||||||
|
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
|
||||||
|
// See pgx.Rows documentation to close the returned Rows and return the acquired connection to the Pool.
|
||||||
|
//
|
||||||
|
// If there is an error, the returned pgx.Rows will be returned in an error state.
|
||||||
|
// If preferred, ignore the error returned from Query and handle errors using the returned pgx.Rows.
|
||||||
|
//
|
||||||
|
// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and
|
||||||
|
// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely
|
||||||
|
// needed. See the documentation for those types for details.
|
||||||
|
func (p *Pool) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errRows{err: err}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := c.Query(ctx, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
c.Release()
|
||||||
|
return errRows{err: err}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.getPoolRows(rows), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRow acquires a connection and executes a query that is expected
|
||||||
|
// to return at most one row (pgx.Row). Errors are deferred until pgx.Row's
|
||||||
|
// Scan method is called. If the query selects no rows, pgx.Row's Scan will
|
||||||
|
// return ErrNoRows. Otherwise, pgx.Row's Scan scans the first selected row
|
||||||
|
// and discards the rest. The acquired connection is returned to the Pool when
|
||||||
|
// pgx.Row's Scan method is called.
|
||||||
|
//
|
||||||
|
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
|
||||||
|
//
|
||||||
|
// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and
|
||||||
|
// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely
|
||||||
|
// needed. See the documentation for those types for details.
|
||||||
|
func (p *Pool) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errRow{err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
row := c.QueryRow(ctx, sql, args...)
|
||||||
|
return c.getPoolRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errBatchResults{err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
br := c.SendBatch(ctx, b)
|
||||||
|
return &poolBatchResults{br: br, c: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin acquires a connection from the Pool and starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no
|
||||||
|
// auto-rollback on context cancellation. Begin initiates a transaction block without explicitly setting a transaction mode for the block (see BeginTx with TxOptions if transaction mode is required).
|
||||||
|
// *pgxpool.Tx is returned, which implements the pgx.Tx interface.
|
||||||
|
// Commit or Rollback must be called on the returned transaction to finalize the transaction block.
|
||||||
|
func (p *Pool) Begin(ctx context.Context) (pgx.Tx, error) {
|
||||||
|
return p.BeginTx(ctx, pgx.TxOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeginTx acquires a connection from the Pool and starts a transaction with pgx.TxOptions determining the transaction mode.
|
||||||
|
// Unlike database/sql, the context only affects the begin command. i.e. there is no auto-rollback on context cancellation.
|
||||||
|
// *pgxpool.Tx is returned, which implements the pgx.Tx interface.
|
||||||
|
// Commit or Rollback must be called on the returned transaction to finalize the transaction block.
|
||||||
|
func (p *Pool) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := c.BeginTx(ctx, txOptions)
|
||||||
|
if err != nil {
|
||||||
|
c.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Tx{t: t, c: c}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer c.Release()
|
||||||
|
|
||||||
|
return c.Conn().CopyFrom(ctx, tableName, columnNames, rowSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping acquires a connection from the Pool and executes an empty sql statement against it.
|
||||||
|
// If the sql returns without error, the database Ping is considered successful, otherwise, the error is returned.
|
||||||
|
func (p *Pool) Ping(ctx context.Context) error {
|
||||||
|
c, err := p.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer c.Release()
|
||||||
|
return c.Ping(ctx)
|
||||||
|
}
|
116
vendor/github.com/jackc/pgx/v5/pgxpool/rows.go
generated
vendored
Normal file
116
vendor/github.com/jackc/pgx/v5/pgxpool/rows.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errRows struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (errRows) Close() {}
|
||||||
|
func (e errRows) Err() error { return e.err }
|
||||||
|
func (errRows) CommandTag() pgconn.CommandTag { return pgconn.CommandTag{} }
|
||||||
|
func (errRows) FieldDescriptions() []pgconn.FieldDescription { return nil }
|
||||||
|
func (errRows) Next() bool { return false }
|
||||||
|
func (e errRows) Scan(dest ...any) error { return e.err }
|
||||||
|
func (e errRows) Values() ([]any, error) { return nil, e.err }
|
||||||
|
func (e errRows) RawValues() [][]byte { return nil }
|
||||||
|
func (e errRows) Conn() *pgx.Conn { return nil }
|
||||||
|
|
||||||
|
type errRow struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e errRow) Scan(dest ...any) error { return e.err }
|
||||||
|
|
||||||
|
type poolRows struct {
|
||||||
|
r pgx.Rows
|
||||||
|
c *Conn
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Close() {
|
||||||
|
rows.r.Close()
|
||||||
|
if rows.c != nil {
|
||||||
|
rows.c.Release()
|
||||||
|
rows.c = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Err() error {
|
||||||
|
if rows.err != nil {
|
||||||
|
return rows.err
|
||||||
|
}
|
||||||
|
return rows.r.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) CommandTag() pgconn.CommandTag {
|
||||||
|
return rows.r.CommandTag()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) FieldDescriptions() []pgconn.FieldDescription {
|
||||||
|
return rows.r.FieldDescriptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Next() bool {
|
||||||
|
if rows.err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
n := rows.r.Next()
|
||||||
|
if !n {
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Scan(dest ...any) error {
|
||||||
|
err := rows.r.Scan(dest...)
|
||||||
|
if err != nil {
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Values() ([]any, error) {
|
||||||
|
values, err := rows.r.Values()
|
||||||
|
if err != nil {
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
return values, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) RawValues() [][]byte {
|
||||||
|
return rows.r.RawValues()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rows *poolRows) Conn() *pgx.Conn {
|
||||||
|
return rows.r.Conn()
|
||||||
|
}
|
||||||
|
|
||||||
|
type poolRow struct {
|
||||||
|
r pgx.Row
|
||||||
|
c *Conn
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (row *poolRow) Scan(dest ...any) error {
|
||||||
|
if row.err != nil {
|
||||||
|
return row.err
|
||||||
|
}
|
||||||
|
|
||||||
|
panicked := true
|
||||||
|
defer func() {
|
||||||
|
if panicked && row.c != nil {
|
||||||
|
row.c.Release()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err := row.r.Scan(dest...)
|
||||||
|
panicked = false
|
||||||
|
if row.c != nil {
|
||||||
|
row.c.Release()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
84
vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
generated
vendored
Normal file
84
vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/puddle/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stat is a snapshot of Pool statistics.
|
||||||
|
type Stat struct {
|
||||||
|
s *puddle.Stat
|
||||||
|
newConnsCount int64
|
||||||
|
lifetimeDestroyCount int64
|
||||||
|
idleDestroyCount int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireCount returns the cumulative count of successful acquires from the pool.
|
||||||
|
func (s *Stat) AcquireCount() int64 {
|
||||||
|
return s.s.AcquireCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireDuration returns the total duration of all successful acquires from
|
||||||
|
// the pool.
|
||||||
|
func (s *Stat) AcquireDuration() time.Duration {
|
||||||
|
return s.s.AcquireDuration()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquiredConns returns the number of currently acquired connections in the pool.
|
||||||
|
func (s *Stat) AcquiredConns() int32 {
|
||||||
|
return s.s.AcquiredResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanceledAcquireCount returns the cumulative count of acquires from the pool
|
||||||
|
// that were canceled by a context.
|
||||||
|
func (s *Stat) CanceledAcquireCount() int64 {
|
||||||
|
return s.s.CanceledAcquireCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstructingConns returns the number of conns with construction in progress in
|
||||||
|
// the pool.
|
||||||
|
func (s *Stat) ConstructingConns() int32 {
|
||||||
|
return s.s.ConstructingResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyAcquireCount returns the cumulative count of successful acquires from the pool
|
||||||
|
// that waited for a resource to be released or constructed because the pool was
|
||||||
|
// empty.
|
||||||
|
func (s *Stat) EmptyAcquireCount() int64 {
|
||||||
|
return s.s.EmptyAcquireCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdleConns returns the number of currently idle conns in the pool.
|
||||||
|
func (s *Stat) IdleConns() int32 {
|
||||||
|
return s.s.IdleResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxConns returns the maximum size of the pool.
|
||||||
|
func (s *Stat) MaxConns() int32 {
|
||||||
|
return s.s.MaxResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalConns returns the total number of resources currently in the pool.
|
||||||
|
// The value is the sum of ConstructingConns, AcquiredConns, and
|
||||||
|
// IdleConns.
|
||||||
|
func (s *Stat) TotalConns() int32 {
|
||||||
|
return s.s.TotalResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConnsCount returns the cumulative count of new connections opened.
|
||||||
|
func (s *Stat) NewConnsCount() int64 {
|
||||||
|
return s.newConnsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxLifetimeDestroyCount returns the cumulative count of connections destroyed
|
||||||
|
// because they exceeded MaxConnLifetime.
|
||||||
|
func (s *Stat) MaxLifetimeDestroyCount() int64 {
|
||||||
|
return s.lifetimeDestroyCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxIdleDestroyCount returns the cumulative count of connections destroyed because
|
||||||
|
// they exceeded MaxConnIdleTime.
|
||||||
|
func (s *Stat) MaxIdleDestroyCount() int64 {
|
||||||
|
return s.idleDestroyCount
|
||||||
|
}
|
82
vendor/github.com/jackc/pgx/v5/pgxpool/tx.go
generated
vendored
Normal file
82
vendor/github.com/jackc/pgx/v5/pgxpool/tx.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package pgxpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tx represents a database transaction acquired from a Pool.
|
||||||
|
type Tx struct {
|
||||||
|
t pgx.Tx
|
||||||
|
c *Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin starts a pseudo nested transaction implemented with a savepoint.
|
||||||
|
func (tx *Tx) Begin(ctx context.Context) (pgx.Tx, error) {
|
||||||
|
return tx.t.Begin(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit commits the transaction and returns the associated connection back to the Pool. Commit will return ErrTxClosed
|
||||||
|
// if the Tx is already closed, but is otherwise safe to call multiple times. If the commit fails with a rollback status
|
||||||
|
// (e.g. the transaction was already in a broken state) then ErrTxCommitRollback will be returned.
|
||||||
|
func (tx *Tx) Commit(ctx context.Context) error {
|
||||||
|
err := tx.t.Commit(ctx)
|
||||||
|
if tx.c != nil {
|
||||||
|
tx.c.Release()
|
||||||
|
tx.c = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback rolls back the transaction and returns the associated connection back to the Pool. Rollback will return ErrTxClosed
|
||||||
|
// if the Tx is already closed, but is otherwise safe to call multiple times. Hence, defer tx.Rollback() is safe even if
|
||||||
|
// tx.Commit() will be called first in a non-error condition.
|
||||||
|
func (tx *Tx) Rollback(ctx context.Context) error {
|
||||||
|
err := tx.t.Rollback(ctx)
|
||||||
|
if tx.c != nil {
|
||||||
|
tx.c.Release()
|
||||||
|
tx.c = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) {
|
||||||
|
return tx.t.CopyFrom(ctx, tableName, columnNames, rowSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults {
|
||||||
|
return tx.t.SendBatch(ctx, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) LargeObjects() pgx.LargeObjects {
|
||||||
|
return tx.t.LargeObjects()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare creates a prepared statement with name and sql. If the name is empty,
|
||||||
|
// an anonymous prepared statement will be used. sql can contain placeholders
|
||||||
|
// for bound parameters. These placeholders are referenced positionally as $1, $2, etc.
|
||||||
|
//
|
||||||
|
// Prepare is idempotent; i.e. it is safe to call Prepare multiple times with the same
|
||||||
|
// name and sql arguments. This allows a code path to Prepare and Query/Exec without
|
||||||
|
// needing to first check whether the statement has already been prepared.
|
||||||
|
func (tx *Tx) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
|
||||||
|
return tx.t.Prepare(ctx, name, sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error) {
|
||||||
|
return tx.t.Exec(ctx, sql, arguments...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) {
|
||||||
|
return tx.t.Query(ctx, sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row {
|
||||||
|
return tx.t.QueryRow(ctx, sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Tx) Conn() *pgx.Conn {
|
||||||
|
return tx.t.Conn()
|
||||||
|
}
|
66
vendor/github.com/jackc/pgx/v5/rows.go
generated
vendored
66
vendor/github.com/jackc/pgx/v5/rows.go
generated
vendored
@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/internal/stmtcache"
|
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,8 @@ import (
|
|||||||
// the *Conn can be used again. Rows are closed by explicitly calling Close(),
|
// the *Conn can be used again. Rows are closed by explicitly calling Close(),
|
||||||
// calling Next() until it returns false, or when a fatal error occurs.
|
// calling Next() until it returns false, or when a fatal error occurs.
|
||||||
//
|
//
|
||||||
// Once a Rows is closed the only methods that may be called are Close(), Err(), and CommandTag().
|
// Once a Rows is closed the only methods that may be called are Close(), Err(),
|
||||||
|
// and CommandTag().
|
||||||
//
|
//
|
||||||
// Rows is an interface instead of a struct to allow tests to mock Query. However,
|
// Rows is an interface instead of a struct to allow tests to mock Query. However,
|
||||||
// adding a method to an interface is technically a breaking change. Because of this
|
// adding a method to an interface is technically a breaking change. Because of this
|
||||||
@ -41,8 +41,15 @@ type Rows interface {
|
|||||||
FieldDescriptions() []pgconn.FieldDescription
|
FieldDescriptions() []pgconn.FieldDescription
|
||||||
|
|
||||||
// Next prepares the next row for reading. It returns true if there is another
|
// Next prepares the next row for reading. It returns true if there is another
|
||||||
// row and false if no more rows are available. It automatically closes rows
|
// row and false if no more rows are available or a fatal error has occurred.
|
||||||
// when all rows are read.
|
// It automatically closes rows when all rows are read.
|
||||||
|
//
|
||||||
|
// Callers should check rows.Err() after rows.Next() returns false to detect
|
||||||
|
// whether result-set reading ended prematurely due to an error. See
|
||||||
|
// Conn.Query for details.
|
||||||
|
//
|
||||||
|
// For simpler error handling, consider using the higher-level pgx v5
|
||||||
|
// CollectRows() and ForEachRow() helpers instead.
|
||||||
Next() bool
|
Next() bool
|
||||||
|
|
||||||
// Scan reads the values from the current row into dest values positionally.
|
// Scan reads the values from the current row into dest values positionally.
|
||||||
@ -166,7 +173,6 @@ func (rows *baseRows) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rows.err != nil && rows.conn != nil && rows.sql != "" {
|
if rows.err != nil && rows.conn != nil && rows.sql != "" {
|
||||||
if stmtcache.IsStatementInvalid(rows.err) {
|
|
||||||
if sc := rows.conn.statementCache; sc != nil {
|
if sc := rows.conn.statementCache; sc != nil {
|
||||||
sc.Invalidate(rows.sql)
|
sc.Invalidate(rows.sql)
|
||||||
}
|
}
|
||||||
@ -175,7 +181,6 @@ func (rows *baseRows) Close() {
|
|||||||
sc.Invalidate(rows.sql)
|
sc.Invalidate(rows.sql)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if rows.batchTracer != nil {
|
if rows.batchTracer != nil {
|
||||||
rows.batchTracer.TraceBatchQuery(rows.ctx, rows.conn, TraceBatchQueryData{SQL: rows.sql, Args: rows.args, CommandTag: rows.commandTag, Err: rows.err})
|
rows.batchTracer.TraceBatchQuery(rows.ctx, rows.conn, TraceBatchQueryData{SQL: rows.sql, Args: rows.args, CommandTag: rows.commandTag, Err: rows.err})
|
||||||
@ -457,6 +462,39 @@ func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
|
|||||||
return value, rows.Err()
|
return value, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollectExactlyOneRow calls fn for the first row in rows and returns the result.
|
||||||
|
// - If no rows are found returns an error where errors.Is(ErrNoRows) is true.
|
||||||
|
// - If more than 1 row is found returns an error where errors.Is(ErrTooManyRows) is true.
|
||||||
|
func CollectExactlyOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
value T
|
||||||
|
)
|
||||||
|
|
||||||
|
if !rows.Next() {
|
||||||
|
if err = rows.Err(); err != nil {
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err = fn(rows)
|
||||||
|
if err != nil {
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rows.Next() {
|
||||||
|
var zero T
|
||||||
|
|
||||||
|
return zero, ErrTooManyRows
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// RowTo returns a T scanned from row.
|
// RowTo returns a T scanned from row.
|
||||||
func RowTo[T any](row CollectableRow) (T, error) {
|
func RowTo[T any](row CollectableRow) (T, error) {
|
||||||
var value T
|
var value T
|
||||||
@ -496,7 +534,7 @@ func (rs *mapRowScanner) ScanRow(rows Rows) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row
|
// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row
|
||||||
// has fields. The row and T fields will by matched by position. If the "db" struct tag is "-" then the field will be
|
// has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then the field will be
|
||||||
// ignored.
|
// ignored.
|
||||||
func RowToStructByPos[T any](row CollectableRow) (T, error) {
|
func RowToStructByPos[T any](row CollectableRow) (T, error) {
|
||||||
var value T
|
var value T
|
||||||
@ -505,7 +543,7 @@ func RowToStructByPos[T any](row CollectableRow) (T, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToAddrOfStructByPos returns the address of a T scanned from row. T must be a struct. T must have the same number a
|
// RowToAddrOfStructByPos returns the address of a T scanned from row. T must be a struct. T must have the same number a
|
||||||
// public fields as row has fields. The row and T fields will by matched by position. If the "db" struct tag is "-" then
|
// public fields as row has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then
|
||||||
// the field will be ignored.
|
// the field will be ignored.
|
||||||
func RowToAddrOfStructByPos[T any](row CollectableRow) (*T, error) {
|
func RowToAddrOfStructByPos[T any](row CollectableRow) (*T, error) {
|
||||||
var value T
|
var value T
|
||||||
@ -560,7 +598,7 @@ func (rs *positionalStructRowScanner) appendScanTargets(dstElemValue reflect.Val
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToStructByName returns a T scanned from row. T must be a struct. T must have the same number of named public
|
// RowToStructByName returns a T scanned from row. T must be a struct. T must have the same number of named public
|
||||||
// fields as row has fields. The row and T fields will by matched by name. The match is case-insensitive. The database
|
// fields as row has fields. The row and T fields will be matched by name. The match is case-insensitive. The database
|
||||||
// column name can be overridden with a "db" struct tag. If the "db" struct tag is "-" then the field will be ignored.
|
// column name can be overridden with a "db" struct tag. If the "db" struct tag is "-" then the field will be ignored.
|
||||||
func RowToStructByName[T any](row CollectableRow) (T, error) {
|
func RowToStructByName[T any](row CollectableRow) (T, error) {
|
||||||
var value T
|
var value T
|
||||||
@ -569,7 +607,7 @@ func RowToStructByName[T any](row CollectableRow) (T, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToAddrOfStructByName returns the address of a T scanned from row. T must be a struct. T must have the same number
|
// RowToAddrOfStructByName returns the address of a T scanned from row. T must be a struct. T must have the same number
|
||||||
// of named public fields as row has fields. The row and T fields will by matched by name. The match is
|
// of named public fields as row has fields. The row and T fields will be matched by name. The match is
|
||||||
// case-insensitive. The database column name can be overridden with a "db" struct tag. If the "db" struct tag is "-"
|
// case-insensitive. The database column name can be overridden with a "db" struct tag. If the "db" struct tag is "-"
|
||||||
// then the field will be ignored.
|
// then the field will be ignored.
|
||||||
func RowToAddrOfStructByName[T any](row CollectableRow) (*T, error) {
|
func RowToAddrOfStructByName[T any](row CollectableRow) (*T, error) {
|
||||||
@ -579,7 +617,7 @@ func RowToAddrOfStructByName[T any](row CollectableRow) (*T, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToStructByNameLax returns a T scanned from row. T must be a struct. T must have greater than or equal number of named public
|
// RowToStructByNameLax returns a T scanned from row. T must be a struct. T must have greater than or equal number of named public
|
||||||
// fields as row has fields. The row and T fields will by matched by name. The match is case-insensitive. The database
|
// fields as row has fields. The row and T fields will be matched by name. The match is case-insensitive. The database
|
||||||
// column name can be overridden with a "db" struct tag. If the "db" struct tag is "-" then the field will be ignored.
|
// column name can be overridden with a "db" struct tag. If the "db" struct tag is "-" then the field will be ignored.
|
||||||
func RowToStructByNameLax[T any](row CollectableRow) (T, error) {
|
func RowToStructByNameLax[T any](row CollectableRow) (T, error) {
|
||||||
var value T
|
var value T
|
||||||
@ -588,7 +626,7 @@ func RowToStructByNameLax[T any](row CollectableRow) (T, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RowToAddrOfStructByNameLax returns the address of a T scanned from row. T must be a struct. T must have greater than or
|
// RowToAddrOfStructByNameLax returns the address of a T scanned from row. T must be a struct. T must have greater than or
|
||||||
// equal number of named public fields as row has fields. The row and T fields will by matched by name. The match is
|
// equal number of named public fields as row has fields. The row and T fields will be matched by name. The match is
|
||||||
// case-insensitive. The database column name can be overridden with a "db" struct tag. If the "db" struct tag is "-"
|
// case-insensitive. The database column name can be overridden with a "db" struct tag. If the "db" struct tag is "-"
|
||||||
// then the field will be ignored.
|
// then the field will be ignored.
|
||||||
func RowToAddrOfStructByNameLax[T any](row CollectableRow) (*T, error) {
|
func RowToAddrOfStructByNameLax[T any](row CollectableRow) (*T, error) {
|
||||||
@ -650,7 +688,7 @@ func (rs *namedStructRowScanner) appendScanTargets(dstElemValue reflect.Value, s
|
|||||||
// Field is unexported, skip it.
|
// Field is unexported, skip it.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Handle anoymous struct embedding, but do not try to handle embedded pointers.
|
// Handle anonymous struct embedding, but do not try to handle embedded pointers.
|
||||||
if sf.Anonymous && sf.Type.Kind() == reflect.Struct {
|
if sf.Anonymous && sf.Type.Kind() == reflect.Struct {
|
||||||
scanTargets, err = rs.appendScanTargets(dstElemValue.Field(i), scanTargets, fldDescs)
|
scanTargets, err = rs.appendScanTargets(dstElemValue.Field(i), scanTargets, fldDescs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -659,7 +697,7 @@ func (rs *namedStructRowScanner) appendScanTargets(dstElemValue reflect.Value, s
|
|||||||
} else {
|
} else {
|
||||||
dbTag, dbTagPresent := sf.Tag.Lookup(structTagKey)
|
dbTag, dbTagPresent := sf.Tag.Lookup(structTagKey)
|
||||||
if dbTagPresent {
|
if dbTagPresent {
|
||||||
dbTag = strings.Split(dbTag, ",")[0]
|
dbTag, _, _ = strings.Cut(dbTag, ",")
|
||||||
}
|
}
|
||||||
if dbTag == "-" {
|
if dbTag == "-" {
|
||||||
// Field is ignored, skip it.
|
// Field is ignored, skip it.
|
||||||
|
117
vendor/github.com/jackc/pgx/v5/stdlib/sql.go
generated
vendored
117
vendor/github.com/jackc/pgx/v5/stdlib/sql.go
generated
vendored
@ -14,6 +14,18 @@
|
|||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// Or from a *pgxpool.Pool.
|
||||||
|
//
|
||||||
|
// pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// db, err := stdlib.OpenDBFromPool(pool)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
// Or a pgx.ConnConfig can be used to set configuration not accessible via connection string. In this case the
|
// Or a pgx.ConnConfig can be used to set configuration not accessible via connection string. In this case the
|
||||||
// pgx.ConnConfig must first be registered with the driver. This registration returns a connection string which is used
|
// pgx.ConnConfig must first be registered with the driver. This registration returns a connection string which is used
|
||||||
// with sql.Open.
|
// with sql.Open.
|
||||||
@ -74,6 +86,7 @@ import (
|
|||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Only intrinsic types should be binary format with database/sql.
|
// Only intrinsic types should be binary format with database/sql.
|
||||||
@ -125,14 +138,14 @@ func contains(list []string, y string) bool {
|
|||||||
type OptionOpenDB func(*connector)
|
type OptionOpenDB func(*connector)
|
||||||
|
|
||||||
// OptionBeforeConnect provides a callback for before connect. It is passed a shallow copy of the ConnConfig that will
|
// OptionBeforeConnect provides a callback for before connect. It is passed a shallow copy of the ConnConfig that will
|
||||||
// be used to connect, so only its immediate members should be modified.
|
// be used to connect, so only its immediate members should be modified. Used only if db is opened with *pgx.ConnConfig.
|
||||||
func OptionBeforeConnect(bc func(context.Context, *pgx.ConnConfig) error) OptionOpenDB {
|
func OptionBeforeConnect(bc func(context.Context, *pgx.ConnConfig) error) OptionOpenDB {
|
||||||
return func(dc *connector) {
|
return func(dc *connector) {
|
||||||
dc.BeforeConnect = bc
|
dc.BeforeConnect = bc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OptionAfterConnect provides a callback for after connect.
|
// OptionAfterConnect provides a callback for after connect. Used only if db is opened with *pgx.ConnConfig.
|
||||||
func OptionAfterConnect(ac func(context.Context, *pgx.Conn) error) OptionOpenDB {
|
func OptionAfterConnect(ac func(context.Context, *pgx.Conn) error) OptionOpenDB {
|
||||||
return func(dc *connector) {
|
return func(dc *connector) {
|
||||||
dc.AfterConnect = ac
|
dc.AfterConnect = ac
|
||||||
@ -191,13 +204,42 @@ func GetConnector(config pgx.ConnConfig, opts ...OptionOpenDB) driver.Connector
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPoolConnector creates a new driver.Connector from the given *pgxpool.Pool. By using this be sure to set the
|
||||||
|
// maximum idle connections of the *sql.DB created with this connector to zero since they must be managed from the
|
||||||
|
// *pgxpool.Pool. This is required to avoid acquiring all the connections from the pgxpool and starving any direct
|
||||||
|
// users of the pgxpool.
|
||||||
|
func GetPoolConnector(pool *pgxpool.Pool, opts ...OptionOpenDB) driver.Connector {
|
||||||
|
c := connector{
|
||||||
|
pool: pool,
|
||||||
|
ResetSession: func(context.Context, *pgx.Conn) error { return nil }, // noop reset session by default
|
||||||
|
driver: pgxDriver,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB {
|
func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB {
|
||||||
c := GetConnector(config, opts...)
|
c := GetConnector(config, opts...)
|
||||||
return sql.OpenDB(c)
|
return sql.OpenDB(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenDBFromPool creates a new *sql.DB from the given *pgxpool.Pool. Note that this method automatically sets the
|
||||||
|
// maximum number of idle connections in *sql.DB to zero, since they must be managed from the *pgxpool.Pool. This is
|
||||||
|
// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool.
|
||||||
|
func OpenDBFromPool(pool *pgxpool.Pool, opts ...OptionOpenDB) *sql.DB {
|
||||||
|
c := GetPoolConnector(pool, opts...)
|
||||||
|
db := sql.OpenDB(c)
|
||||||
|
db.SetMaxIdleConns(0)
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
type connector struct {
|
type connector struct {
|
||||||
pgx.ConnConfig
|
pgx.ConnConfig
|
||||||
|
pool *pgxpool.Pool
|
||||||
BeforeConnect func(context.Context, *pgx.ConnConfig) error // function to call before creation of every new connection
|
BeforeConnect func(context.Context, *pgx.ConnConfig) error // function to call before creation of every new connection
|
||||||
AfterConnect func(context.Context, *pgx.Conn) error // function to call after creation of every new connection
|
AfterConnect func(context.Context, *pgx.Conn) error // function to call after creation of every new connection
|
||||||
ResetSession func(context.Context, *pgx.Conn) error // function is called before a connection is reused
|
ResetSession func(context.Context, *pgx.Conn) error // function is called before a connection is reused
|
||||||
@ -207,12 +249,16 @@ type connector struct {
|
|||||||
// Connect implement driver.Connector interface
|
// Connect implement driver.Connector interface
|
||||||
func (c connector) Connect(ctx context.Context) (driver.Conn, error) {
|
func (c connector) Connect(ctx context.Context) (driver.Conn, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
connConfig pgx.ConnConfig
|
||||||
conn *pgx.Conn
|
conn *pgx.Conn
|
||||||
|
close func(context.Context) error
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if c.pool == nil {
|
||||||
// Create a shallow copy of the config, so that BeforeConnect can safely modify it
|
// Create a shallow copy of the config, so that BeforeConnect can safely modify it
|
||||||
connConfig := c.ConnConfig
|
connConfig = c.ConnConfig
|
||||||
|
|
||||||
if err = c.BeforeConnect(ctx, &connConfig); err != nil {
|
if err = c.BeforeConnect(ctx, &connConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -225,7 +271,31 @@ func (c connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Conn{conn: conn, driver: c.driver, connConfig: connConfig, resetSessionFunc: c.ResetSession}, nil
|
close = conn.Close
|
||||||
|
} else {
|
||||||
|
var pconn *pgxpool.Conn
|
||||||
|
|
||||||
|
pconn, err = c.pool.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = pconn.Conn()
|
||||||
|
|
||||||
|
close = func(_ context.Context) error {
|
||||||
|
pconn.Release()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Conn{
|
||||||
|
conn: conn,
|
||||||
|
close: close,
|
||||||
|
driver: c.driver,
|
||||||
|
connConfig: connConfig,
|
||||||
|
resetSessionFunc: c.ResetSession,
|
||||||
|
psRefCounts: make(map[*pgconn.StatementDescription]int),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver implement driver.Connector interface
|
// Driver implement driver.Connector interface
|
||||||
@ -302,9 +372,11 @@ func (dc *driverConnector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||||||
|
|
||||||
c := &Conn{
|
c := &Conn{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
|
close: conn.Close,
|
||||||
driver: dc.driver,
|
driver: dc.driver,
|
||||||
connConfig: *connConfig,
|
connConfig: *connConfig,
|
||||||
resetSessionFunc: func(context.Context, *pgx.Conn) error { return nil },
|
resetSessionFunc: func(context.Context, *pgx.Conn) error { return nil },
|
||||||
|
psRefCounts: make(map[*pgconn.StatementDescription]int),
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
@ -326,11 +398,19 @@ func UnregisterConnConfig(connStr string) {
|
|||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
conn *pgx.Conn
|
conn *pgx.Conn
|
||||||
psCount int64 // Counter used for creating unique prepared statement names
|
close func(context.Context) error
|
||||||
driver *Driver
|
driver *Driver
|
||||||
connConfig pgx.ConnConfig
|
connConfig pgx.ConnConfig
|
||||||
resetSessionFunc func(context.Context, *pgx.Conn) error // Function is called before a connection is reused
|
resetSessionFunc func(context.Context, *pgx.Conn) error // Function is called before a connection is reused
|
||||||
lastResetSessionTime time.Time
|
lastResetSessionTime time.Time
|
||||||
|
|
||||||
|
// psRefCounts contains reference counts for prepared statements. Prepare uses the underlying pgx logic to generate
|
||||||
|
// deterministic statement names from the statement text. If this query has already been prepared then the existing
|
||||||
|
// *pgconn.StatementDescription will be returned. However, this means that if Close is called on the returned Stmt
|
||||||
|
// then the underlying prepared statement will be closed even when the underlying prepared statement is still in use
|
||||||
|
// by another database/sql Stmt. To prevent this psRefCounts keeps track of how many database/sql statements are using
|
||||||
|
// the same underlying statement and only closes the underlying statement when the reference count reaches 0.
|
||||||
|
psRefCounts map[*pgconn.StatementDescription]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conn returns the underlying *pgx.Conn
|
// Conn returns the underlying *pgx.Conn
|
||||||
@ -347,13 +427,11 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, e
|
|||||||
return nil, driver.ErrBadConn
|
return nil, driver.ErrBadConn
|
||||||
}
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("pgx_%d", c.psCount)
|
sd, err := c.conn.Prepare(ctx, query, query)
|
||||||
c.psCount++
|
|
||||||
|
|
||||||
sd, err := c.conn.Prepare(ctx, name, query)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
c.psRefCounts[sd]++
|
||||||
|
|
||||||
return &Stmt{sd: sd, conn: c}, nil
|
return &Stmt{sd: sd, conn: c}, nil
|
||||||
}
|
}
|
||||||
@ -361,7 +439,7 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, e
|
|||||||
func (c *Conn) Close() error {
|
func (c *Conn) Close() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return c.conn.Close(ctx)
|
return c.close(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Begin() (driver.Tx, error) {
|
func (c *Conn) Begin() (driver.Tx, error) {
|
||||||
@ -470,7 +548,7 @@ func (c *Conn) ResetSession(ctx context.Context) error {
|
|||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if now.Sub(c.lastResetSessionTime) > time.Second {
|
if now.Sub(c.lastResetSessionTime) > time.Second {
|
||||||
if err := c.conn.PgConn().CheckConn(); err != nil {
|
if err := c.conn.PgConn().Ping(ctx); err != nil {
|
||||||
return driver.ErrBadConn
|
return driver.ErrBadConn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -487,7 +565,16 @@ type Stmt struct {
|
|||||||
func (s *Stmt) Close() error {
|
func (s *Stmt) Close() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return s.conn.conn.Deallocate(ctx, s.sd.Name)
|
|
||||||
|
refCount := s.conn.psRefCounts[s.sd]
|
||||||
|
if refCount == 1 {
|
||||||
|
delete(s.conn.psRefCounts, s.sd)
|
||||||
|
} else {
|
||||||
|
s.conn.psRefCounts[s.sd]--
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.conn.conn.Deallocate(ctx, s.sd.SQL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) NumInput() int {
|
func (s *Stmt) NumInput() int {
|
||||||
@ -499,7 +586,7 @@ func (s *Stmt) Exec(argsV []driver.Value) (driver.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) ExecContext(ctx context.Context, argsV []driver.NamedValue) (driver.Result, error) {
|
func (s *Stmt) ExecContext(ctx context.Context, argsV []driver.NamedValue) (driver.Result, error) {
|
||||||
return s.conn.ExecContext(ctx, s.sd.Name, argsV)
|
return s.conn.ExecContext(ctx, s.sd.SQL, argsV)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Query(argsV []driver.Value) (driver.Rows, error) {
|
func (s *Stmt) Query(argsV []driver.Value) (driver.Rows, error) {
|
||||||
@ -507,7 +594,7 @@ func (s *Stmt) Query(argsV []driver.Value) (driver.Rows, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) QueryContext(ctx context.Context, argsV []driver.NamedValue) (driver.Rows, error) {
|
func (s *Stmt) QueryContext(ctx context.Context, argsV []driver.NamedValue) (driver.Rows, error) {
|
||||||
return s.conn.QueryContext(ctx, s.sd.Name, argsV)
|
return s.conn.QueryContext(ctx, s.sd.SQL, argsV)
|
||||||
}
|
}
|
||||||
|
|
||||||
type rowValueFunc func(src []byte) (driver.Value, error)
|
type rowValueFunc func(src []byte) (driver.Value, error)
|
||||||
|
74
vendor/github.com/jackc/puddle/v2/CHANGELOG.md
generated
vendored
Normal file
74
vendor/github.com/jackc/puddle/v2/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# 2.2.1 (July 15, 2023)
|
||||||
|
|
||||||
|
* Fix: CreateResource cannot overflow pool. This changes documented behavior of CreateResource. Previously,
|
||||||
|
CreateResource could create a resource even if the pool was full. This could cause the pool to overflow. While this
|
||||||
|
was documented, it was documenting incorrect behavior. CreateResource now returns an error if the pool is full.
|
||||||
|
|
||||||
|
# 2.2.0 (February 11, 2023)
|
||||||
|
|
||||||
|
* Use Go 1.19 atomics and drop go.uber.org/atomic dependency
|
||||||
|
|
||||||
|
# 2.1.2 (November 12, 2022)
|
||||||
|
|
||||||
|
* Restore support to Go 1.18 via go.uber.org/atomic
|
||||||
|
|
||||||
|
# 2.1.1 (November 11, 2022)
|
||||||
|
|
||||||
|
* Fix create resource concurrently with Stat call race
|
||||||
|
|
||||||
|
# 2.1.0 (October 28, 2022)
|
||||||
|
|
||||||
|
* Concurrency control is now implemented with a semaphore. This simplifies some internal logic, resolves a few error conditions (including a deadlock), and improves performance. (Jan Dubsky)
|
||||||
|
* Go 1.19 is now required for the improved atomic support.
|
||||||
|
|
||||||
|
# 2.0.1 (October 28, 2022)
|
||||||
|
|
||||||
|
* Fix race condition when Close is called concurrently with multiple constructors
|
||||||
|
|
||||||
|
# 2.0.0 (September 17, 2022)
|
||||||
|
|
||||||
|
* Use generics instead of interface{} (Столяров Владимир Алексеевич)
|
||||||
|
* Add Reset
|
||||||
|
* Do not cancel resource construction when Acquire is canceled
|
||||||
|
* NewPool takes Config
|
||||||
|
|
||||||
|
# 1.3.0 (August 27, 2022)
|
||||||
|
|
||||||
|
* Acquire creates resources in background to allow creation to continue after Acquire is canceled (James Hartig)
|
||||||
|
|
||||||
|
# 1.2.1 (December 2, 2021)
|
||||||
|
|
||||||
|
* TryAcquire now does not block when background constructing resource
|
||||||
|
|
||||||
|
# 1.2.0 (November 20, 2021)
|
||||||
|
|
||||||
|
* Add TryAcquire (A. Jensen)
|
||||||
|
* Fix: remove memory leak / unintentionally pinned memory when shrinking slices (Alexander Staubo)
|
||||||
|
* Fix: Do not leave pool locked after panic from nil context
|
||||||
|
|
||||||
|
# 1.1.4 (September 11, 2021)
|
||||||
|
|
||||||
|
* Fix: Deadlock in CreateResource if pool was closed during resource acquisition (Dmitriy Matrenichev)
|
||||||
|
|
||||||
|
# 1.1.3 (December 3, 2020)
|
||||||
|
|
||||||
|
* Fix: Failed resource creation could cause concurrent Acquire to hang. (Evgeny Vanslov)
|
||||||
|
|
||||||
|
# 1.1.2 (September 26, 2020)
|
||||||
|
|
||||||
|
* Fix: Resource.Destroy no longer removes itself from the pool before its destructor has completed.
|
||||||
|
* Fix: Prevent crash when pool is closed while resource is being created.
|
||||||
|
|
||||||
|
# 1.1.1 (April 2, 2020)
|
||||||
|
|
||||||
|
* Pool.Close can be safely called multiple times
|
||||||
|
* AcquireAllIDle immediately returns nil if pool is closed
|
||||||
|
* CreateResource checks if pool is closed before taking any action
|
||||||
|
* Fix potential race condition when CreateResource and Close are called concurrently. CreateResource now checks if pool is closed before adding newly created resource to pool.
|
||||||
|
|
||||||
|
# 1.1.0 (February 5, 2020)
|
||||||
|
|
||||||
|
* Use runtime.nanotime for faster tracking of acquire time and last usage time.
|
||||||
|
* Track resource idle time to enable client health check logic. (Patrick Ellul)
|
||||||
|
* Add CreateResource to construct a new resource without acquiring it. (Patrick Ellul)
|
||||||
|
* Fix deadlock race when acquire is cancelled. (Michael Tharp)
|
22
vendor/github.com/jackc/puddle/v2/LICENSE
generated
vendored
Normal file
22
vendor/github.com/jackc/puddle/v2/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2018 Jack Christensen
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
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.
|
80
vendor/github.com/jackc/puddle/v2/README.md
generated
vendored
Normal file
80
vendor/github.com/jackc/puddle/v2/README.md
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
[](https://godoc.org/github.com/jackc/puddle)
|
||||||
|

|
||||||
|
|
||||||
|
# Puddle
|
||||||
|
|
||||||
|
Puddle is a tiny generic resource pool library for Go that uses the standard
|
||||||
|
context library to signal cancellation of acquires. It is designed to contain
|
||||||
|
the minimum functionality required for a resource pool. It can be used directly
|
||||||
|
or it can be used as the base for a domain specific resource pool. For example,
|
||||||
|
a database connection pool may use puddle internally and implement health checks
|
||||||
|
and keep-alive behavior without needing to implement any concurrent code of its
|
||||||
|
own.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Acquire cancellation via context standard library
|
||||||
|
* Statistics API for monitoring pool pressure
|
||||||
|
* No dependencies outside of standard library and golang.org/x/sync
|
||||||
|
* High performance
|
||||||
|
* 100% test coverage of reachable code
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/jackc/puddle/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
constructor := func(context.Context) (net.Conn, error) {
|
||||||
|
return net.Dial("tcp", "127.0.0.1:8080")
|
||||||
|
}
|
||||||
|
destructor := func(value net.Conn) {
|
||||||
|
value.Close()
|
||||||
|
}
|
||||||
|
maxPoolSize := int32(10)
|
||||||
|
|
||||||
|
pool, err := puddle.NewPool(&puddle.Config[net.Conn]{Constructor: constructor, Destructor: destructor, MaxSize: maxPoolSize})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire resource from the pool.
|
||||||
|
res, err := pool.Acquire(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use resource.
|
||||||
|
_, err = res.Value().Write([]byte{1})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release when done.
|
||||||
|
res.Release()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Puddle is stable and feature complete.
|
||||||
|
|
||||||
|
* Bug reports and fixes are welcome.
|
||||||
|
* New features will usually not be accepted if they can be feasibly implemented in a wrapper.
|
||||||
|
* Performance optimizations will usually not be accepted unless the performance issue rises to the level of a bug.
|
||||||
|
|
||||||
|
## Supported Go Versions
|
||||||
|
|
||||||
|
puddle supports the same versions of Go that are supported by the Go project. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases. This means puddle supports Go 1.19 and higher.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
24
vendor/github.com/jackc/puddle/v2/context.go
generated
vendored
Normal file
24
vendor/github.com/jackc/puddle/v2/context.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package puddle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// valueCancelCtx combines two contexts into one. One context is used for values and the other is used for cancellation.
|
||||||
|
type valueCancelCtx struct {
|
||||||
|
valueCtx context.Context
|
||||||
|
cancelCtx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *valueCancelCtx) Deadline() (time.Time, bool) { return ctx.cancelCtx.Deadline() }
|
||||||
|
func (ctx *valueCancelCtx) Done() <-chan struct{} { return ctx.cancelCtx.Done() }
|
||||||
|
func (ctx *valueCancelCtx) Err() error { return ctx.cancelCtx.Err() }
|
||||||
|
func (ctx *valueCancelCtx) Value(key any) any { return ctx.valueCtx.Value(key) }
|
||||||
|
|
||||||
|
func newValueCancelCtx(valueCtx, cancelContext context.Context) context.Context {
|
||||||
|
return &valueCancelCtx{
|
||||||
|
valueCtx: valueCtx,
|
||||||
|
cancelCtx: cancelContext,
|
||||||
|
}
|
||||||
|
}
|
11
vendor/github.com/jackc/puddle/v2/doc.go
generated
vendored
Normal file
11
vendor/github.com/jackc/puddle/v2/doc.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Package puddle is a generic resource pool with type-parametrized api.
|
||||||
|
/*
|
||||||
|
|
||||||
|
Puddle is a tiny generic resource pool library for Go that uses the standard
|
||||||
|
context library to signal cancellation of acquires. It is designed to contain
|
||||||
|
the minimum functionality a resource pool needs that cannot be implemented
|
||||||
|
without concurrency concerns. For example, a database connection pool may use
|
||||||
|
puddle internally and implement health checks and keep-alive behavior without
|
||||||
|
needing to implement any concurrent code of its own.
|
||||||
|
*/
|
||||||
|
package puddle
|
85
vendor/github.com/jackc/puddle/v2/internal/genstack/gen_stack.go
generated
vendored
Normal file
85
vendor/github.com/jackc/puddle/v2/internal/genstack/gen_stack.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package genstack
|
||||||
|
|
||||||
|
// GenStack implements a generational stack.
|
||||||
|
//
|
||||||
|
// GenStack works as common stack except for the fact that all elements in the
|
||||||
|
// older generation are guaranteed to be popped before any element in the newer
|
||||||
|
// generation. New elements are always pushed to the current (newest)
|
||||||
|
// generation.
|
||||||
|
//
|
||||||
|
// We could also say that GenStack behaves as a stack in case of a single
|
||||||
|
// generation, but it behaves as a queue of individual generation stacks.
|
||||||
|
type GenStack[T any] struct {
|
||||||
|
// We can represent arbitrary number of generations using 2 stacks. The
|
||||||
|
// new stack stores all new pushes and the old stack serves all reads.
|
||||||
|
// Old stack can represent multiple generations. If old == new, then all
|
||||||
|
// elements pushed in previous (not current) generations have already
|
||||||
|
// been popped.
|
||||||
|
|
||||||
|
old *stack[T]
|
||||||
|
new *stack[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenStack creates a new empty GenStack.
|
||||||
|
func NewGenStack[T any]() *GenStack[T] {
|
||||||
|
s := &stack[T]{}
|
||||||
|
return &GenStack[T]{
|
||||||
|
old: s,
|
||||||
|
new: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *GenStack[T]) Pop() (T, bool) {
|
||||||
|
// Pushes always append to the new stack, so if the old once becomes
|
||||||
|
// empty, it will remail empty forever.
|
||||||
|
if s.old.len() == 0 && s.old != s.new {
|
||||||
|
s.old = s.new
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.old.len() == 0 {
|
||||||
|
var zero T
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.old.pop(), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push pushes a new element at the top of the stack.
|
||||||
|
func (s *GenStack[T]) Push(v T) { s.new.push(v) }
|
||||||
|
|
||||||
|
// NextGen starts a new stack generation.
|
||||||
|
func (s *GenStack[T]) NextGen() {
|
||||||
|
if s.old == s.new {
|
||||||
|
s.new = &stack[T]{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to pop from the old stack to the top of the new stack. Let's
|
||||||
|
// have an example:
|
||||||
|
//
|
||||||
|
// Old: <bottom> 4 3 2 1
|
||||||
|
// New: <bottom> 8 7 6 5
|
||||||
|
// PopOrder: 1 2 3 4 5 6 7 8
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// To preserve pop order, we have to take all elements from the old
|
||||||
|
// stack and push them to the top of new stack:
|
||||||
|
//
|
||||||
|
// New: 8 7 6 5 4 3 2 1
|
||||||
|
//
|
||||||
|
s.new.push(s.old.takeAll()...)
|
||||||
|
|
||||||
|
// We have the old stack allocated and empty, so why not to reuse it as
|
||||||
|
// new new stack.
|
||||||
|
s.old, s.new = s.new, s.old
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns number of elements in the stack.
|
||||||
|
func (s *GenStack[T]) Len() int {
|
||||||
|
l := s.old.len()
|
||||||
|
if s.old != s.new {
|
||||||
|
l += s.new.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
39
vendor/github.com/jackc/puddle/v2/internal/genstack/stack.go
generated
vendored
Normal file
39
vendor/github.com/jackc/puddle/v2/internal/genstack/stack.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package genstack
|
||||||
|
|
||||||
|
// stack is a wrapper around an array implementing a stack.
|
||||||
|
//
|
||||||
|
// We cannot use slice to represent the stack because append might change the
|
||||||
|
// pointer value of the slice. That would be an issue in GenStack
|
||||||
|
// implementation.
|
||||||
|
type stack[T any] struct {
|
||||||
|
arr []T
|
||||||
|
}
|
||||||
|
|
||||||
|
// push pushes a new element at the top of a stack.
|
||||||
|
func (s *stack[T]) push(vs ...T) { s.arr = append(s.arr, vs...) }
|
||||||
|
|
||||||
|
// pop pops the stack top-most element.
|
||||||
|
//
|
||||||
|
// If stack length is zero, this method panics.
|
||||||
|
func (s *stack[T]) pop() T {
|
||||||
|
idx := s.len() - 1
|
||||||
|
val := s.arr[idx]
|
||||||
|
|
||||||
|
// Avoid memory leak
|
||||||
|
var zero T
|
||||||
|
s.arr[idx] = zero
|
||||||
|
|
||||||
|
s.arr = s.arr[:idx]
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// takeAll returns all elements in the stack in order as they are stored - i.e.
|
||||||
|
// the top-most stack element is the last one.
|
||||||
|
func (s *stack[T]) takeAll() []T {
|
||||||
|
arr := s.arr
|
||||||
|
s.arr = nil
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// len returns number of elements in the stack.
|
||||||
|
func (s *stack[T]) len() int { return len(s.arr) }
|
32
vendor/github.com/jackc/puddle/v2/log.go
generated
vendored
Normal file
32
vendor/github.com/jackc/puddle/v2/log.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package puddle
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type ints interface {
|
||||||
|
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// log2Int returns log2 of an integer. This function panics if val < 0. For val
|
||||||
|
// == 0, returns 0.
|
||||||
|
func log2Int[T ints](val T) uint8 {
|
||||||
|
if val <= 0 {
|
||||||
|
panic("log2 of non-positive number does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
return log2IntRange(val, 0, uint8(8*unsafe.Sizeof(val)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func log2IntRange[T ints](val T, begin, end uint8) uint8 {
|
||||||
|
length := end - begin
|
||||||
|
if length == 1 {
|
||||||
|
return begin
|
||||||
|
}
|
||||||
|
|
||||||
|
delim := begin + length/2
|
||||||
|
mask := T(1) << delim
|
||||||
|
if mask > val {
|
||||||
|
return log2IntRange(val, begin, delim)
|
||||||
|
} else {
|
||||||
|
return log2IntRange(val, delim, end)
|
||||||
|
}
|
||||||
|
}
|
13
vendor/github.com/jackc/puddle/v2/nanotime_time.go
generated
vendored
Normal file
13
vendor/github.com/jackc/puddle/v2/nanotime_time.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//go:build purego || appengine || js
|
||||||
|
|
||||||
|
// This file contains the safe implementation of nanotime using time.Now().
|
||||||
|
|
||||||
|
package puddle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nanotime() int64 {
|
||||||
|
return time.Now().UnixNano()
|
||||||
|
}
|
12
vendor/github.com/jackc/puddle/v2/nanotime_unsafe.go
generated
vendored
Normal file
12
vendor/github.com/jackc/puddle/v2/nanotime_unsafe.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//go:build !purego && !appengine && !js
|
||||||
|
|
||||||
|
// This file contains the implementation of nanotime using runtime.nanotime.
|
||||||
|
|
||||||
|
package puddle
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
var _ = unsafe.Sizeof(0)
|
||||||
|
|
||||||
|
//go:linkname nanotime runtime.nanotime
|
||||||
|
func nanotime() int64
|
696
vendor/github.com/jackc/puddle/v2/pool.go
generated
vendored
Normal file
696
vendor/github.com/jackc/puddle/v2/pool.go
generated
vendored
Normal file
@ -0,0 +1,696 @@
|
|||||||
|
package puddle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/puddle/v2/internal/genstack"
|
||||||
|
"golang.org/x/sync/semaphore"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
resourceStatusConstructing = 0
|
||||||
|
resourceStatusIdle = iota
|
||||||
|
resourceStatusAcquired = iota
|
||||||
|
resourceStatusHijacked = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrClosedPool occurs on an attempt to acquire a connection from a closed pool
|
||||||
|
// or a pool that is closed while the acquire is waiting.
|
||||||
|
var ErrClosedPool = errors.New("closed pool")
|
||||||
|
|
||||||
|
// ErrNotAvailable occurs on an attempt to acquire a resource from a pool
|
||||||
|
// that is at maximum capacity and has no available resources.
|
||||||
|
var ErrNotAvailable = errors.New("resource not available")
|
||||||
|
|
||||||
|
// Constructor is a function called by the pool to construct a resource.
|
||||||
|
type Constructor[T any] func(ctx context.Context) (res T, err error)
|
||||||
|
|
||||||
|
// Destructor is a function called by the pool to destroy a resource.
|
||||||
|
type Destructor[T any] func(res T)
|
||||||
|
|
||||||
|
// Resource is the resource handle returned by acquiring from the pool.
|
||||||
|
type Resource[T any] struct {
|
||||||
|
value T
|
||||||
|
pool *Pool[T]
|
||||||
|
creationTime time.Time
|
||||||
|
lastUsedNano int64
|
||||||
|
poolResetCount int
|
||||||
|
status byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the resource value.
|
||||||
|
func (res *Resource[T]) Value() T {
|
||||||
|
if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
|
||||||
|
panic("tried to access resource that is not acquired or hijacked")
|
||||||
|
}
|
||||||
|
return res.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release returns the resource to the pool. res must not be subsequently used.
|
||||||
|
func (res *Resource[T]) Release() {
|
||||||
|
if res.status != resourceStatusAcquired {
|
||||||
|
panic("tried to release resource that is not acquired")
|
||||||
|
}
|
||||||
|
res.pool.releaseAcquiredResource(res, nanotime())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleaseUnused returns the resource to the pool without updating when it was last used used. i.e. LastUsedNanotime
|
||||||
|
// will not change. res must not be subsequently used.
|
||||||
|
func (res *Resource[T]) ReleaseUnused() {
|
||||||
|
if res.status != resourceStatusAcquired {
|
||||||
|
panic("tried to release resource that is not acquired")
|
||||||
|
}
|
||||||
|
res.pool.releaseAcquiredResource(res, res.lastUsedNano)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy returns the resource to the pool for destruction. res must not be
|
||||||
|
// subsequently used.
|
||||||
|
func (res *Resource[T]) Destroy() {
|
||||||
|
if res.status != resourceStatusAcquired {
|
||||||
|
panic("tried to destroy resource that is not acquired")
|
||||||
|
}
|
||||||
|
go res.pool.destroyAcquiredResource(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hijack assumes ownership of the resource from the pool. Caller is responsible
|
||||||
|
// for cleanup of resource value.
|
||||||
|
func (res *Resource[T]) Hijack() {
|
||||||
|
if res.status != resourceStatusAcquired {
|
||||||
|
panic("tried to hijack resource that is not acquired")
|
||||||
|
}
|
||||||
|
res.pool.hijackAcquiredResource(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreationTime returns when the resource was created by the pool.
|
||||||
|
func (res *Resource[T]) CreationTime() time.Time {
|
||||||
|
if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
|
||||||
|
panic("tried to access resource that is not acquired or hijacked")
|
||||||
|
}
|
||||||
|
return res.creationTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastUsedNanotime returns when Release was last called on the resource measured in nanoseconds from an arbitrary time
|
||||||
|
// (a monotonic time). Returns creation time if Release has never been called. This is only useful to compare with
|
||||||
|
// other calls to LastUsedNanotime. In almost all cases, IdleDuration should be used instead.
|
||||||
|
func (res *Resource[T]) LastUsedNanotime() int64 {
|
||||||
|
if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
|
||||||
|
panic("tried to access resource that is not acquired or hijacked")
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.lastUsedNano
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdleDuration returns the duration since Release was last called on the resource. This is equivalent to subtracting
|
||||||
|
// LastUsedNanotime to the current nanotime.
|
||||||
|
func (res *Resource[T]) IdleDuration() time.Duration {
|
||||||
|
if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
|
||||||
|
panic("tried to access resource that is not acquired or hijacked")
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Duration(nanotime() - res.lastUsedNano)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool is a concurrency-safe resource pool.
|
||||||
|
type Pool[T any] struct {
|
||||||
|
// mux is the pool internal lock. Any modification of shared state of
|
||||||
|
// the pool (but Acquires of acquireSem) must be performed only by
|
||||||
|
// holder of the lock. Long running operations are not allowed when mux
|
||||||
|
// is held.
|
||||||
|
mux sync.Mutex
|
||||||
|
// acquireSem provides an allowance to acquire a resource.
|
||||||
|
//
|
||||||
|
// Releases are allowed only when caller holds mux. Acquires have to
|
||||||
|
// happen before mux is locked (doesn't apply to semaphore.TryAcquire in
|
||||||
|
// AcquireAllIdle).
|
||||||
|
acquireSem *semaphore.Weighted
|
||||||
|
destructWG sync.WaitGroup
|
||||||
|
|
||||||
|
allResources resList[T]
|
||||||
|
idleResources *genstack.GenStack[*Resource[T]]
|
||||||
|
|
||||||
|
constructor Constructor[T]
|
||||||
|
destructor Destructor[T]
|
||||||
|
maxSize int32
|
||||||
|
|
||||||
|
acquireCount int64
|
||||||
|
acquireDuration time.Duration
|
||||||
|
emptyAcquireCount int64
|
||||||
|
canceledAcquireCount atomic.Int64
|
||||||
|
|
||||||
|
resetCount int
|
||||||
|
|
||||||
|
baseAcquireCtx context.Context
|
||||||
|
cancelBaseAcquireCtx context.CancelFunc
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config[T any] struct {
|
||||||
|
Constructor Constructor[T]
|
||||||
|
Destructor Destructor[T]
|
||||||
|
MaxSize int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPool creates a new pool. Panics if maxSize is less than 1.
|
||||||
|
func NewPool[T any](config *Config[T]) (*Pool[T], error) {
|
||||||
|
if config.MaxSize < 1 {
|
||||||
|
return nil, errors.New("MaxSize must be >= 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
baseAcquireCtx, cancelBaseAcquireCtx := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
return &Pool[T]{
|
||||||
|
acquireSem: semaphore.NewWeighted(int64(config.MaxSize)),
|
||||||
|
idleResources: genstack.NewGenStack[*Resource[T]](),
|
||||||
|
maxSize: config.MaxSize,
|
||||||
|
constructor: config.Constructor,
|
||||||
|
destructor: config.Destructor,
|
||||||
|
baseAcquireCtx: baseAcquireCtx,
|
||||||
|
cancelBaseAcquireCtx: cancelBaseAcquireCtx,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close destroys all resources in the pool and rejects future Acquire calls.
|
||||||
|
// Blocks until all resources are returned to pool and destroyed.
|
||||||
|
func (p *Pool[T]) Close() {
|
||||||
|
defer p.destructWG.Wait()
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
if p.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.closed = true
|
||||||
|
p.cancelBaseAcquireCtx()
|
||||||
|
|
||||||
|
for res, ok := p.idleResources.Pop(); ok; res, ok = p.idleResources.Pop() {
|
||||||
|
p.allResources.remove(res)
|
||||||
|
go p.destructResourceValue(res.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat is a snapshot of Pool statistics.
|
||||||
|
type Stat struct {
|
||||||
|
constructingResources int32
|
||||||
|
acquiredResources int32
|
||||||
|
idleResources int32
|
||||||
|
maxResources int32
|
||||||
|
acquireCount int64
|
||||||
|
acquireDuration time.Duration
|
||||||
|
emptyAcquireCount int64
|
||||||
|
canceledAcquireCount int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalResources returns the total number of resources currently in the pool.
|
||||||
|
// The value is the sum of ConstructingResources, AcquiredResources, and
|
||||||
|
// IdleResources.
|
||||||
|
func (s *Stat) TotalResources() int32 {
|
||||||
|
return s.constructingResources + s.acquiredResources + s.idleResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstructingResources returns the number of resources with construction in progress in
|
||||||
|
// the pool.
|
||||||
|
func (s *Stat) ConstructingResources() int32 {
|
||||||
|
return s.constructingResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquiredResources returns the number of currently acquired resources in the pool.
|
||||||
|
func (s *Stat) AcquiredResources() int32 {
|
||||||
|
return s.acquiredResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdleResources returns the number of currently idle resources in the pool.
|
||||||
|
func (s *Stat) IdleResources() int32 {
|
||||||
|
return s.idleResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxResources returns the maximum size of the pool.
|
||||||
|
func (s *Stat) MaxResources() int32 {
|
||||||
|
return s.maxResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireCount returns the cumulative count of successful acquires from the pool.
|
||||||
|
func (s *Stat) AcquireCount() int64 {
|
||||||
|
return s.acquireCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireDuration returns the total duration of all successful acquires from
|
||||||
|
// the pool.
|
||||||
|
func (s *Stat) AcquireDuration() time.Duration {
|
||||||
|
return s.acquireDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyAcquireCount returns the cumulative count of successful acquires from the pool
|
||||||
|
// that waited for a resource to be released or constructed because the pool was
|
||||||
|
// empty.
|
||||||
|
func (s *Stat) EmptyAcquireCount() int64 {
|
||||||
|
return s.emptyAcquireCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanceledAcquireCount returns the cumulative count of acquires from the pool
|
||||||
|
// that were canceled by a context.
|
||||||
|
func (s *Stat) CanceledAcquireCount() int64 {
|
||||||
|
return s.canceledAcquireCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns the current pool statistics.
|
||||||
|
func (p *Pool[T]) Stat() *Stat {
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
s := &Stat{
|
||||||
|
maxResources: p.maxSize,
|
||||||
|
acquireCount: p.acquireCount,
|
||||||
|
emptyAcquireCount: p.emptyAcquireCount,
|
||||||
|
canceledAcquireCount: p.canceledAcquireCount.Load(),
|
||||||
|
acquireDuration: p.acquireDuration,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, res := range p.allResources {
|
||||||
|
switch res.status {
|
||||||
|
case resourceStatusConstructing:
|
||||||
|
s.constructingResources += 1
|
||||||
|
case resourceStatusIdle:
|
||||||
|
s.idleResources += 1
|
||||||
|
case resourceStatusAcquired:
|
||||||
|
s.acquiredResources += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryAcquireIdleResource checks if there is any idle resource. If there is
|
||||||
|
// some, this method removes it from idle list and returns it. If the idle pool
|
||||||
|
// is empty, this method returns nil and doesn't modify the idleResources slice.
|
||||||
|
//
|
||||||
|
// WARNING: Caller of this method must hold the pool mutex!
|
||||||
|
func (p *Pool[T]) tryAcquireIdleResource() *Resource[T] {
|
||||||
|
res, ok := p.idleResources.Pop()
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status = resourceStatusAcquired
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// createNewResource creates a new resource and inserts it into list of pool
|
||||||
|
// resources.
|
||||||
|
//
|
||||||
|
// WARNING: Caller of this method must hold the pool mutex!
|
||||||
|
func (p *Pool[T]) createNewResource() *Resource[T] {
|
||||||
|
res := &Resource[T]{
|
||||||
|
pool: p,
|
||||||
|
creationTime: time.Now(),
|
||||||
|
lastUsedNano: nanotime(),
|
||||||
|
poolResetCount: p.resetCount,
|
||||||
|
status: resourceStatusConstructing,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.allResources.append(res)
|
||||||
|
p.destructWG.Add(1)
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire gets a resource from the pool. If no resources are available and the pool is not at maximum capacity it will
|
||||||
|
// create a new resource. If the pool is at maximum capacity it will block until a resource is available. ctx can be
|
||||||
|
// used to cancel the Acquire.
|
||||||
|
//
|
||||||
|
// If Acquire creates a new resource the resource constructor function will receive a context that delegates Value() to
|
||||||
|
// ctx. Canceling ctx will cause Acquire to return immediately but it will not cancel the resource creation. This avoids
|
||||||
|
// the problem of it being impossible to create resources when the time to create a resource is greater than any one
|
||||||
|
// caller of Acquire is willing to wait.
|
||||||
|
func (p *Pool[T]) Acquire(ctx context.Context) (_ *Resource[T], err error) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
p.canceledAcquireCount.Add(1)
|
||||||
|
return nil, ctx.Err()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.acquire(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// acquire is a continuation of Acquire function that doesn't check context
|
||||||
|
// validity.
|
||||||
|
//
|
||||||
|
// This function exists solely only for benchmarking purposes.
|
||||||
|
func (p *Pool[T]) acquire(ctx context.Context) (*Resource[T], error) {
|
||||||
|
startNano := nanotime()
|
||||||
|
|
||||||
|
var waitedForLock bool
|
||||||
|
if !p.acquireSem.TryAcquire(1) {
|
||||||
|
waitedForLock = true
|
||||||
|
err := p.acquireSem.Acquire(ctx, 1)
|
||||||
|
if err != nil {
|
||||||
|
p.canceledAcquireCount.Add(1)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
if p.closed {
|
||||||
|
p.acquireSem.Release(1)
|
||||||
|
p.mux.Unlock()
|
||||||
|
return nil, ErrClosedPool
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a resource is available in the pool.
|
||||||
|
if res := p.tryAcquireIdleResource(); res != nil {
|
||||||
|
if waitedForLock {
|
||||||
|
p.emptyAcquireCount += 1
|
||||||
|
}
|
||||||
|
p.acquireCount += 1
|
||||||
|
p.acquireDuration += time.Duration(nanotime() - startNano)
|
||||||
|
p.mux.Unlock()
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.allResources) >= int(p.maxSize) {
|
||||||
|
// Unreachable code.
|
||||||
|
panic("bug: semaphore allowed more acquires than pool allows")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The resource is not idle, but there is enough space to create one.
|
||||||
|
res := p.createNewResource()
|
||||||
|
p.mux.Unlock()
|
||||||
|
|
||||||
|
res, err := p.initResourceValue(ctx, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
p.emptyAcquireCount += 1
|
||||||
|
p.acquireCount += 1
|
||||||
|
p.acquireDuration += time.Duration(nanotime() - startNano)
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool[T]) initResourceValue(ctx context.Context, res *Resource[T]) (*Resource[T], error) {
|
||||||
|
// Create the resource in a goroutine to immediately return from Acquire
|
||||||
|
// if ctx is canceled without also canceling the constructor.
|
||||||
|
//
|
||||||
|
// See:
|
||||||
|
// - https://github.com/jackc/pgx/issues/1287
|
||||||
|
// - https://github.com/jackc/pgx/issues/1259
|
||||||
|
constructErrChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
constructorCtx := newValueCancelCtx(ctx, p.baseAcquireCtx)
|
||||||
|
value, err := p.constructor(constructorCtx)
|
||||||
|
if err != nil {
|
||||||
|
p.mux.Lock()
|
||||||
|
p.allResources.remove(res)
|
||||||
|
p.destructWG.Done()
|
||||||
|
|
||||||
|
// The resource won't be acquired because its
|
||||||
|
// construction failed. We have to allow someone else to
|
||||||
|
// take that resouce.
|
||||||
|
p.acquireSem.Release(1)
|
||||||
|
p.mux.Unlock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case constructErrChan <- err:
|
||||||
|
case <-ctx.Done():
|
||||||
|
// The caller is cancelled, so no-one awaits the
|
||||||
|
// error. This branch avoid goroutine leak.
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// The resource is already in p.allResources where it might be read. So we need to acquire the lock to update its
|
||||||
|
// status.
|
||||||
|
p.mux.Lock()
|
||||||
|
res.value = value
|
||||||
|
res.status = resourceStatusAcquired
|
||||||
|
p.mux.Unlock()
|
||||||
|
|
||||||
|
// This select works because the channel is unbuffered.
|
||||||
|
select {
|
||||||
|
case constructErrChan <- nil:
|
||||||
|
case <-ctx.Done():
|
||||||
|
p.releaseAcquiredResource(res, res.lastUsedNano)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
p.canceledAcquireCount.Add(1)
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case err := <-constructErrChan:
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryAcquire gets a resource from the pool if one is immediately available. If not, it returns ErrNotAvailable. If no
|
||||||
|
// resources are available but the pool has room to grow, a resource will be created in the background. ctx is only
|
||||||
|
// used to cancel the background creation.
|
||||||
|
func (p *Pool[T]) TryAcquire(ctx context.Context) (*Resource[T], error) {
|
||||||
|
if !p.acquireSem.TryAcquire(1) {
|
||||||
|
return nil, ErrNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
if p.closed {
|
||||||
|
p.acquireSem.Release(1)
|
||||||
|
return nil, ErrClosedPool
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a resource is available now
|
||||||
|
if res := p.tryAcquireIdleResource(); res != nil {
|
||||||
|
p.acquireCount += 1
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.allResources) >= int(p.maxSize) {
|
||||||
|
// Unreachable code.
|
||||||
|
panic("bug: semaphore allowed more acquires than pool allows")
|
||||||
|
}
|
||||||
|
|
||||||
|
res := p.createNewResource()
|
||||||
|
go func() {
|
||||||
|
value, err := p.constructor(ctx)
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
// We have to create the resource and only then release the
|
||||||
|
// semaphore - For the time being there is no resource that
|
||||||
|
// someone could acquire.
|
||||||
|
defer p.acquireSem.Release(1)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
p.allResources.remove(res)
|
||||||
|
p.destructWG.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.value = value
|
||||||
|
res.status = resourceStatusIdle
|
||||||
|
p.idleResources.Push(res)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil, ErrNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
// acquireSemAll tries to acquire num free tokens from sem. This function is
|
||||||
|
// guaranteed to acquire at least the lowest number of tokens that has been
|
||||||
|
// available in the semaphore during runtime of this function.
|
||||||
|
//
|
||||||
|
// For the time being, semaphore doesn't allow to acquire all tokens atomically
|
||||||
|
// (see https://github.com/golang/sync/pull/19). We simulate this by trying all
|
||||||
|
// powers of 2 that are less or equal to num.
|
||||||
|
//
|
||||||
|
// For example, let's immagine we have 19 free tokens in the semaphore which in
|
||||||
|
// total has 24 tokens (i.e. the maxSize of the pool is 24 resources). Then if
|
||||||
|
// num is 24, the log2Uint(24) is 4 and we try to acquire 16, 8, 4, 2 and 1
|
||||||
|
// tokens. Out of those, the acquire of 16, 2 and 1 tokens will succeed.
|
||||||
|
//
|
||||||
|
// Naturally, Acquires and Releases of the semaphore might take place
|
||||||
|
// concurrently. For this reason, it's not guaranteed that absolutely all free
|
||||||
|
// tokens in the semaphore will be acquired. But it's guaranteed that at least
|
||||||
|
// the minimal number of tokens that has been present over the whole process
|
||||||
|
// will be acquired. This is sufficient for the use-case we have in this
|
||||||
|
// package.
|
||||||
|
//
|
||||||
|
// TODO: Replace this with acquireSem.TryAcquireAll() if it gets to
|
||||||
|
// upstream. https://github.com/golang/sync/pull/19
|
||||||
|
func acquireSemAll(sem *semaphore.Weighted, num int) int {
|
||||||
|
if sem.TryAcquire(int64(num)) {
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
var acquired int
|
||||||
|
for i := int(log2Int(num)); i >= 0; i-- {
|
||||||
|
val := 1 << i
|
||||||
|
if sem.TryAcquire(int64(val)) {
|
||||||
|
acquired += val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acquired
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcquireAllIdle acquires all currently idle resources. Its intended use is for
|
||||||
|
// health check and keep-alive functionality. It does not update pool
|
||||||
|
// statistics.
|
||||||
|
func (p *Pool[T]) AcquireAllIdle() []*Resource[T] {
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
if p.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
numIdle := p.idleResources.Len()
|
||||||
|
if numIdle == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// In acquireSemAll we use only TryAcquire and not Acquire. Because
|
||||||
|
// TryAcquire cannot block, the fact that we hold mutex locked and try
|
||||||
|
// to acquire semaphore cannot result in dead-lock.
|
||||||
|
//
|
||||||
|
// Because the mutex is locked, no parallel Release can run. This
|
||||||
|
// implies that the number of tokens can only decrease because some
|
||||||
|
// Acquire/TryAcquire call can consume the semaphore token. Consequently
|
||||||
|
// acquired is always less or equal to numIdle. Moreover if acquired <
|
||||||
|
// numIdle, then there are some parallel Acquire/TryAcquire calls that
|
||||||
|
// will take the remaining idle connections.
|
||||||
|
acquired := acquireSemAll(p.acquireSem, numIdle)
|
||||||
|
|
||||||
|
idle := make([]*Resource[T], acquired)
|
||||||
|
for i := range idle {
|
||||||
|
res, _ := p.idleResources.Pop()
|
||||||
|
res.status = resourceStatusAcquired
|
||||||
|
idle[i] = res
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have to bump the generation to ensure that Acquire/TryAcquire
|
||||||
|
// calls running in parallel (those which caused acquired < numIdle)
|
||||||
|
// will consume old connections and not freshly released connections
|
||||||
|
// instead.
|
||||||
|
p.idleResources.NextGen()
|
||||||
|
|
||||||
|
return idle
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResource constructs a new resource without acquiring it. It goes straight in the IdlePool. If the pool is full
|
||||||
|
// it returns an error. It can be useful to maintain warm resources under little load.
|
||||||
|
func (p *Pool[T]) CreateResource(ctx context.Context) error {
|
||||||
|
if !p.acquireSem.TryAcquire(1) {
|
||||||
|
return ErrNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
if p.closed {
|
||||||
|
p.acquireSem.Release(1)
|
||||||
|
p.mux.Unlock()
|
||||||
|
return ErrClosedPool
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.allResources) >= int(p.maxSize) {
|
||||||
|
p.acquireSem.Release(1)
|
||||||
|
p.mux.Unlock()
|
||||||
|
return ErrNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
res := p.createNewResource()
|
||||||
|
p.mux.Unlock()
|
||||||
|
|
||||||
|
value, err := p.constructor(ctx)
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
defer p.acquireSem.Release(1)
|
||||||
|
if err != nil {
|
||||||
|
p.allResources.remove(res)
|
||||||
|
p.destructWG.Done()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.value = value
|
||||||
|
res.status = resourceStatusIdle
|
||||||
|
|
||||||
|
// If closed while constructing resource then destroy it and return an error
|
||||||
|
if p.closed {
|
||||||
|
go p.destructResourceValue(res.value)
|
||||||
|
return ErrClosedPool
|
||||||
|
}
|
||||||
|
|
||||||
|
p.idleResources.Push(res)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset destroys all resources, but leaves the pool open. It is intended for use when an error is detected that would
|
||||||
|
// disrupt all resources (such as a network interruption or a server state change).
|
||||||
|
//
|
||||||
|
// It is safe to reset a pool while resources are checked out. Those resources will be destroyed when they are returned
|
||||||
|
// to the pool.
|
||||||
|
func (p *Pool[T]) Reset() {
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
|
||||||
|
p.resetCount++
|
||||||
|
|
||||||
|
for res, ok := p.idleResources.Pop(); ok; res, ok = p.idleResources.Pop() {
|
||||||
|
p.allResources.remove(res)
|
||||||
|
go p.destructResourceValue(res.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// releaseAcquiredResource returns res to the the pool.
|
||||||
|
func (p *Pool[T]) releaseAcquiredResource(res *Resource[T], lastUsedNano int64) {
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
defer p.acquireSem.Release(1)
|
||||||
|
|
||||||
|
if p.closed || res.poolResetCount != p.resetCount {
|
||||||
|
p.allResources.remove(res)
|
||||||
|
go p.destructResourceValue(res.value)
|
||||||
|
} else {
|
||||||
|
res.lastUsedNano = lastUsedNano
|
||||||
|
res.status = resourceStatusIdle
|
||||||
|
p.idleResources.Push(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes res from the pool and closes it. If res is not part of the
|
||||||
|
// pool Remove will panic.
|
||||||
|
func (p *Pool[T]) destroyAcquiredResource(res *Resource[T]) {
|
||||||
|
p.destructResourceValue(res.value)
|
||||||
|
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
defer p.acquireSem.Release(1)
|
||||||
|
|
||||||
|
p.allResources.remove(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool[T]) hijackAcquiredResource(res *Resource[T]) {
|
||||||
|
p.mux.Lock()
|
||||||
|
defer p.mux.Unlock()
|
||||||
|
defer p.acquireSem.Release(1)
|
||||||
|
|
||||||
|
p.allResources.remove(res)
|
||||||
|
res.status = resourceStatusHijacked
|
||||||
|
p.destructWG.Done() // not responsible for destructing hijacked resources
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool[T]) destructResourceValue(value T) {
|
||||||
|
p.destructor(value)
|
||||||
|
p.destructWG.Done()
|
||||||
|
}
|
28
vendor/github.com/jackc/puddle/v2/resource_list.go
generated
vendored
Normal file
28
vendor/github.com/jackc/puddle/v2/resource_list.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package puddle
|
||||||
|
|
||||||
|
type resList[T any] []*Resource[T]
|
||||||
|
|
||||||
|
func (l *resList[T]) append(val *Resource[T]) { *l = append(*l, val) }
|
||||||
|
|
||||||
|
func (l *resList[T]) popBack() *Resource[T] {
|
||||||
|
idx := len(*l) - 1
|
||||||
|
val := (*l)[idx]
|
||||||
|
(*l)[idx] = nil // Avoid memory leak
|
||||||
|
*l = (*l)[:idx]
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *resList[T]) remove(val *Resource[T]) {
|
||||||
|
for i, elem := range *l {
|
||||||
|
if elem == val {
|
||||||
|
lastIdx := len(*l) - 1
|
||||||
|
(*l)[i] = (*l)[lastIdx]
|
||||||
|
(*l)[lastIdx] = nil // Avoid memory leak
|
||||||
|
(*l) = (*l)[:lastIdx]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("BUG: removeResource could not find res in slice")
|
||||||
|
}
|
304
vendor/github.com/klauspost/compress/LICENSE
generated
vendored
Normal file
304
vendor/github.com/klauspost/compress/LICENSE
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||||
|
Copyright (c) 2019 Klaus Post. 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.
|
||||||
|
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Files: gzhttp/*
|
||||||
|
|
||||||
|
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 2016-2017 The New York Times Company
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Files: s2/cmd/internal/readahead/*
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Klaus Post
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
Files: snappy/*
|
||||||
|
Files: internal/snapref/*
|
||||||
|
|
||||||
|
Copyright (c) 2011 The Snappy-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.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Files: s2/cmd/internal/filepathx/*
|
||||||
|
|
||||||
|
Copyright 2016 The filepathx Authors
|
||||||
|
|
||||||
|
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.
|
1017
vendor/github.com/klauspost/compress/flate/deflate.go
generated
vendored
Normal file
1017
vendor/github.com/klauspost/compress/flate/deflate.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user