mirror of
https://github.com/kubernetes/sample-controller.git
synced 2026-04-12 00:00:26 +08:00
Compare commits
605 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 91d107945c | |||
| f3ef788c12 | |||
| 0a129f69be | |||
| 862e188e78 | |||
| 135c4c60c0 | |||
| 57c108ffac | |||
| e2a931b1e0 | |||
| 61b0fff013 | |||
| 94623ba852 | |||
| 7cbc2364ff | |||
| e0ad4791f7 | |||
| 6dcce25719 | |||
| 30da3eec49 | |||
| 991499de7e | |||
| 1509cb1ff3 | |||
| 5561807b20 | |||
| 0b991a6b31 | |||
| 3e0e216b84 | |||
| a10f7a69f2 | |||
| 91f2f63250 | |||
| 085c1da033 | |||
| 43a04a6884 | |||
| cc082a837d | |||
| 2a0c700ccd | |||
| 914478ebaa | |||
| 4584dc3378 | |||
| 9ec2064685 | |||
| 8a66ce0ffe | |||
| 8ce9c3c30f | |||
| cf8de9b2c1 | |||
| f47f55a195 | |||
| 3c94deb4df | |||
| 69245a1d17 | |||
| 3ac9ebf2a7 | |||
| c0feae0701 | |||
| 7f244c0dc3 | |||
| 9b81532a60 | |||
| 05144d66df | |||
| 119594ddec | |||
| 28972b75db | |||
| 32ad1389a8 | |||
| 220ca987ad | |||
| 6a2262b4e8 | |||
| 8d405dd3e1 | |||
| 9c27a5a1ab | |||
| b05f3be049 | |||
| b099eae8cd | |||
| 8c90968420 | |||
| 60c19c2a53 | |||
| dcdc54df98 | |||
| 8e0f7d4874 | |||
| a679ea1828 | |||
| 0e1a760a91 | |||
| 7431c5f474 | |||
| f3a6811dd3 | |||
| 709fd539aa | |||
| ea01e096fa | |||
| fef47a8a8e | |||
| 19f6cf7aa7 | |||
| 8865a08dc7 | |||
| 739cecdc1b | |||
| 95cbedd0a1 | |||
| db1ea8ef50 | |||
| 435b20016f | |||
| c693b1e50e | |||
| de4ea5262a | |||
| 5cf44091e8 | |||
| 7d983be3ec | |||
| 9a9f0c5cb9 | |||
| c8fa32cd19 | |||
| ec0e6ae009 | |||
| e0a1db6d08 | |||
| 2699b2b3b2 | |||
| c0c1344b1f | |||
| 4a57a6f070 | |||
| 28bc2cefcd | |||
| 0edc443454 | |||
| 86e7dab20d | |||
| 3709cee765 | |||
| d74f225f28 | |||
| e933a6fa9c | |||
| aadb6d02da | |||
| 96b07c14ac | |||
| c826d9a4ba | |||
| 02b86407e5 | |||
| fac24b192a | |||
| 316b82400f | |||
| 7220d7f7a8 | |||
| 4d73244bb2 | |||
| 9e4d8510b3 | |||
| d9fcada825 | |||
| b569e8beb9 | |||
| 78509bf814 | |||
| 1dd644af46 | |||
| 45f171cd1c | |||
| ee0bf66a6b | |||
| 5ab6bc937a | |||
| 7691be75b7 | |||
| 75fe64a25a | |||
| 48a8b2db1f | |||
| ee41c266dd | |||
| 2e958d3a92 | |||
| a6192a1f94 | |||
| 19901f031d | |||
| 563ed65e6a | |||
| 0f33588e12 | |||
| a81e0d9172 | |||
| abfbe9e320 | |||
| 0ee2ead89a | |||
| c815f58ec6 | |||
| 662273ed7f | |||
| 268409f5e0 | |||
| 219361be1e | |||
| b8b66f86f8 | |||
| b46753e595 | |||
| 4e5c4eae34 | |||
| 55aee52d4f | |||
| 9150b86f3d | |||
| 820568283f | |||
| f1db86b7b1 | |||
| de8d4e7ade | |||
| 8e71b7e744 | |||
| 70d56d6e81 | |||
| ec09503e8c | |||
| d72b96a47c | |||
| 63aa97d0d4 | |||
| 0b94d690a0 | |||
| d043d6ca38 | |||
| 757ba6fd59 | |||
| 53a5db94d7 | |||
| 4d47428cc1 | |||
| e4beb956de | |||
| 90afb4c691 | |||
| dd39d8ad9a | |||
| febdffdd7c | |||
| 81a4aa36e5 | |||
| e012a157e5 | |||
| a9a379dd44 | |||
| e4b0f3541d | |||
| 99e2948a55 | |||
| cec2a01dbb | |||
| 7d2ce28ae6 | |||
| 4f62774764 | |||
| 2ffe381ba2 | |||
| 88f72cf835 | |||
| fcad1cedea | |||
| 8ea3466765 | |||
| b693c98cb2 | |||
| b40f790cb1 | |||
| f6c509e4cb | |||
| d0f41f7d34 | |||
| e14381b695 | |||
| 5bd60b7690 | |||
| 70f6b6db6b | |||
| 7fcc7d1da4 | |||
| b89dfaae4f | |||
| 7525133da7 | |||
| 5db5fb258a | |||
| 90e4a92259 | |||
| c86f57a472 | |||
| 6abd446b44 | |||
| 0acef6e186 | |||
| 1333ecbc49 | |||
| f8051feb77 | |||
| c7e6f3bb3b | |||
| 5903f25886 | |||
| 0ffc5a3b32 | |||
| 4dbbffe1a4 | |||
| 33ebbf8a85 | |||
| feaa5fa984 | |||
| 0deda20119 | |||
| d0c0e1cc70 | |||
| afb5ea4cf2 | |||
| 887900d0a0 | |||
| 08e6755111 | |||
| 4fb65b15f8 | |||
| b7b0a354b2 | |||
| 46c2e4f08e | |||
| f97ac391c8 | |||
| 1297aa3a7b | |||
| e4d1759a29 | |||
| ad3e14a611 | |||
| 7e6f92a49b | |||
| fa80c98bea | |||
| fde0896337 | |||
| 637ec76c82 | |||
| b7a35d54d8 | |||
| 962974946f | |||
| 02ef63233b | |||
| 582615ab52 | |||
| d6829afde3 | |||
| 57eca8415c | |||
| d0e10ce699 | |||
| 906f3c8e97 | |||
| 511f33a332 | |||
| a202d033e8 | |||
| 4a7ee42da4 | |||
| a2dbfe8c0d | |||
| d04cd64012 | |||
| 11b036ee82 | |||
| 563a85b29d | |||
| bf4ca65404 | |||
| 243a9aa31d | |||
| c86d2ce296 | |||
| 7e9e402e3c | |||
| 2e98d2c0d3 | |||
| 74471579f8 | |||
| 43ba8acf92 | |||
| 3a53e68719 | |||
| 26b988f72c | |||
| 78293f14af | |||
| 4d0fe4a863 | |||
| 023a4501a0 | |||
| e4944b9c0c | |||
| 2528528f45 | |||
| f4fe69b0ee | |||
| bf928d19ad | |||
| a6addd6156 | |||
| 334c327e37 | |||
| 282c8d1cd4 | |||
| 055dceebb1 | |||
| 099911c748 | |||
| 3ce5aac867 | |||
| b3350fe1c4 | |||
| 409b230a7d | |||
| 0cd0162dc6 | |||
| 8e9f7ab28f | |||
| 6a72bdf75e | |||
| caef23f0d9 | |||
| 27c29c4213 | |||
| 93527bb948 | |||
| f248b0c2a5 | |||
| 772ba5d3c8 | |||
| 40d31f8ebc | |||
| a688a1ecd6 | |||
| d6aba300cc | |||
| ef84932c51 | |||
| 2a12a88d9a | |||
| ed920bf1ad | |||
| 253089c137 | |||
| 5304c5bbfe | |||
| 42915b2268 | |||
| 7571e5001d | |||
| eff0f430d6 | |||
| efe91cb7e0 | |||
| 87e1c1bd1a | |||
| cb61c988b0 | |||
| 689c5b3466 | |||
| 4939cf473a | |||
| 84793d4167 | |||
| 327d9b9f8c | |||
| ad3e9ae66d | |||
| 894cd0f1b8 | |||
| 49529d823d | |||
| 467e3b47ca | |||
| aa6b1998ce | |||
| 551af0d56f | |||
| 9b9cd32189 | |||
| a116ada776 | |||
| 3a453b8c25 | |||
| ea1c104b16 | |||
| 9c97f6fefe | |||
| 0816ade53e | |||
| b81ac19890 | |||
| d9ca36d6cb | |||
| 627afacaf3 | |||
| 11c95216b3 | |||
| b5e0771c2a | |||
| bb4e0e8f53 | |||
| 2668bcfeaf | |||
| 688abac5e7 | |||
| 67f93556e1 | |||
| 14b633fbd8 | |||
| 9ee3bc5299 | |||
| 0918610fac | |||
| 2be051d821 | |||
| 9f42e5cc2a | |||
| 260ea03d0f | |||
| 25e66d66fa | |||
| 4703f566f3 | |||
| 49c83178d5 | |||
| 0294f2f2a9 | |||
| 7291a6cdf3 | |||
| 7d644bbb9f | |||
| 93bd86992d | |||
| 7719966d92 | |||
| 5ba12bb200 | |||
| 278f9b7dcd | |||
| 2de521cec4 | |||
| b0a4e84ba0 | |||
| af7b1c0694 | |||
| 63f937e6ef | |||
| 563f90bf6c | |||
| c9e3ac4e52 | |||
| c2e0b3138d | |||
| f164169a4c | |||
| f011afbf3e | |||
| c88fa7497a | |||
| 336bb6f273 | |||
| 99679a09ff | |||
| 7668602b23 | |||
| ec8cd975f9 | |||
| a5a87c22d8 | |||
| b4d58f7643 | |||
| 9947546ccd | |||
| 6341ce4f8b | |||
| 43586373cc | |||
| 16472d4993 | |||
| d633df4f51 | |||
| c192b8ab9c | |||
| 21adeefcee | |||
| 90adaf991e | |||
| cf1417c1e6 | |||
| c26f30da20 | |||
| 53327d349f | |||
| 0308619d82 | |||
| 215bd2a002 | |||
| c8e7b205bf | |||
| 2eb1803b4a | |||
| 8b0acfb2d4 | |||
| 0ca051dfd7 | |||
| cb25601369 | |||
| cada21925d | |||
| 42e0dfe5bd | |||
| 97de594ad1 | |||
| f5f8e52055 | |||
| 4f78503155 | |||
| 9c0808159a | |||
| 9b1c43d6d6 | |||
| 54dfd4730b | |||
| d53ffaed67 | |||
| c29cf0e439 | |||
| 720f012c10 | |||
| efdde211f9 | |||
| 1c71ad3324 | |||
| 696bd95bc3 | |||
| 4b8238ee7c | |||
| 158645db01 | |||
| 42ec191006 | |||
| c1e9b90f0d | |||
| 487e715bde | |||
| 6df69c68e4 | |||
| dc3937d923 | |||
| 410966e2f6 | |||
| 158ba2018c | |||
| 5bdae2f497 | |||
| 65d6c2306d | |||
| 398d8887c6 | |||
| e10f69de06 | |||
| 565f8e5b29 | |||
| 8997676e55 | |||
| 769550deee | |||
| 8f3ae5d8de | |||
| 1d259fb1cd | |||
| 0b057f6443 | |||
| 8568d8de9b | |||
| 3681e7519d | |||
| 0d89abf5bb | |||
| c9077cb9dd | |||
| 6fdc9f7abc | |||
| 0d899e8b65 | |||
| c7bdcc10b9 | |||
| b179273133 | |||
| 8e5585d70f | |||
| 59b308f00d | |||
| 330e1b879e | |||
| 788362da34 | |||
| 1cd335f7be | |||
| fb313b8e44 | |||
| 9df0657df8 | |||
| c08795e990 | |||
| 5a86084ff2 | |||
| e9f8ce3407 | |||
| 8176b7f00c | |||
| 259bb91470 | |||
| 38ad360f3b | |||
| 29d058df73 | |||
| 65b04f28b7 | |||
| 2e44acfec6 | |||
| 9eb3ce5279 | |||
| 853296811e | |||
| 33a086b4e3 | |||
| 0db9978b81 | |||
| a8c045e7bd | |||
| 3792e7cfb1 | |||
| 6b6e35066c | |||
| d1209dbc55 | |||
| 2feb1d3234 | |||
| 6916651633 | |||
| ed3486167c | |||
| f52969e798 | |||
| 168c9902bb | |||
| 82020535a7 | |||
| e5c22d4271 | |||
| 03f7b57163 | |||
| 804a6cffcb | |||
| 6dd86d3985 | |||
| 998f1fc70c | |||
| c50d90346a | |||
| bfea6b218c | |||
| a4fd9878f3 | |||
| 12d01daf6f | |||
| 09d4a2aaab | |||
| 5df7172c84 | |||
| a09bb6fcd8 | |||
| 3777cc6812 | |||
| 2d41d75bdb | |||
| 5d5bd9db03 | |||
| 40311fe40c | |||
| 4171db6740 | |||
| 5405add1cc | |||
| 724c2dd696 | |||
| 33dcd114a0 | |||
| 3d43f6a9e3 | |||
| 971dd30cbd | |||
| bb24f00e95 | |||
| aecec8f389 | |||
| 1dc9222795 | |||
| 6f5b028d5b | |||
| 4b40792833 | |||
| 594065de83 | |||
| dee5f8bd63 | |||
| 191c3eb865 | |||
| 26265e9210 | |||
| afa9ca434d | |||
| 4b39461dae | |||
| c921b0fa4a | |||
| bf6cd304f5 | |||
| 5a85cbc030 | |||
| 08ff3cb3cf | |||
| 6e8a7f6c37 | |||
| 273dc7ee93 | |||
| c1307ff006 | |||
| 4aee35773b | |||
| 74fbbf0926 | |||
| 952b67be10 | |||
| bbd1334737 | |||
| 605ac31a64 | |||
| 3ce4d32276 | |||
| d4bdd8e4db | |||
| 805d415d20 | |||
| 764ce3fa41 | |||
| 00be062185 | |||
| 16551df406 | |||
| ca96ac1a97 | |||
| edc30afaf1 | |||
| 9c737fe1e2 | |||
| c36309c95b | |||
| 3f742a73e5 | |||
| 69032f3061 | |||
| 7041378e81 | |||
| e994a938b3 | |||
| b8ceeb6ff4 | |||
| 82dcd15382 | |||
| 6ec5f89077 | |||
| 780aeeea62 | |||
| e78132880d | |||
| a82fd062d8 | |||
| 81254fa334 | |||
| c98f02eb3d | |||
| 82971429f2 | |||
| 774fba113f | |||
| a18bb40927 | |||
| 54004998b9 | |||
| 80ea1c3ad0 | |||
| 52f4e03262 | |||
| 933b6c2033 | |||
| 454e0733e8 | |||
| 5e461fea2d | |||
| 000e0e7d07 | |||
| 1de91ca5e5 | |||
| f021c08271 | |||
| e8d34e91c9 | |||
| ed9e5ed2ab | |||
| 69c3c8b234 | |||
| 1a22429b33 | |||
| c00c0d3837 | |||
| ac45ff67c5 | |||
| 837884cc2d | |||
| 517717199d | |||
| e125907d67 | |||
| aed548591a | |||
| a101c83a5e | |||
| 0672ccd336 | |||
| 66cd9c25b2 | |||
| 088168dd07 | |||
| eee09f85e5 | |||
| 4b88feff70 | |||
| ae6f6816f9 | |||
| 07ac1ce76e | |||
| 7ff6970569 | |||
| 22d0200758 | |||
| b3d6213c85 | |||
| 8ea83ba34f | |||
| faed0acd94 | |||
| 710f47c9d0 | |||
| dbe3983d99 | |||
| 6e95d238b1 | |||
| 6b47cc3175 | |||
| 38c8bea3f4 | |||
| de346b2303 | |||
| 5fd85d3d4d | |||
| 5e6eb18b83 | |||
| 72b2bd3707 | |||
| 2e9136f30d | |||
| 66cc7ece36 | |||
| 874ee36619 | |||
| ed4f24a8c9 | |||
| f1d5a771b1 | |||
| 492ca72ad7 | |||
| e53f833a0d | |||
| 5bc8a4494b | |||
| ad67096f17 | |||
| 23b81d7a14 | |||
| 868912595d | |||
| 7311726853 | |||
| 6b0f2172af | |||
| b8d5491163 | |||
| 4d4bbcc8f6 | |||
| 7d92ac6c14 | |||
| c0e5ca57ef | |||
| 78e8c25006 | |||
| 3676c12417 | |||
| b86e7c6cfd | |||
| ae95116c46 | |||
| e27e0e40c5 | |||
| 9ec49b384a | |||
| 2527447561 | |||
| aaf638eb7a | |||
| 6b0f73bee0 | |||
| 40e9eca108 | |||
| 44c7ffb5f1 | |||
| cbf681e4bc | |||
| fb59b4aa2a | |||
| 51a92d0c5f | |||
| 2be61034e8 | |||
| b58c84c9c6 | |||
| ff0eab27d5 | |||
| d17b4235ba | |||
| c5bf2b05b7 | |||
| 3968700e52 | |||
| 3aea3af533 | |||
| c0f979d47a | |||
| e8a6122bd6 | |||
| 4c2ef7d844 | |||
| c166c2fe4f | |||
| 21d04c9dc6 | |||
| 24ddd1da98 | |||
| fba87c2973 | |||
| 533bf7c2d1 | |||
| 501efb23e7 | |||
| e00c466df8 | |||
| 5b902ecacd | |||
| 9861cadad3 | |||
| 88dd6244c8 | |||
| b9ede25834 | |||
| a32f270ca3 | |||
| f76a51c9a1 | |||
| d865234f0e | |||
| 74fbe5057f | |||
| 03ecb9f167 | |||
| b8b76143ce | |||
| 7df7717190 | |||
| 0d94fd0c60 | |||
| 863b091f8c | |||
| 1c605930c8 | |||
| af680ed1d0 | |||
| af36e57afa | |||
| 0b8ef8e981 | |||
| b13f138dcd | |||
| 489c07a569 | |||
| 9d231f2a2a | |||
| 2f326ff345 | |||
| 8db1716370 | |||
| 33ff92b504 | |||
| 4a1ec65955 | |||
| f647cfe199 | |||
| 994cb3621c | |||
| 83669b2316 | |||
| b6578b5696 | |||
| f1e5514ccc | |||
| 1607ce9716 | |||
| 76d013a3dd | |||
| 7635ea288c | |||
| c98ef8f09b | |||
| 258eead087 | |||
| 735feeca90 | |||
| 9ba34a0e65 | |||
| 92f920f871 | |||
| 9b9d7dbcb1 | |||
| 1c8ed500ee | |||
| bf54256d6b | |||
| 5562881cd1 | |||
| 72bbd3993a | |||
| 8f8c5aedb8 | |||
| 31cb9f1779 | |||
| 49cf8c5ad4 | |||
| 533e85a0fb | |||
| 46b5d73382 | |||
| 756ec2596b | |||
| 1b691d7a53 | |||
| 4d65170555 | |||
| c11b6bcaeb | |||
| 530724013e | |||
| e8d6b5cf83 |
@@ -0,0 +1,2 @@
|
|||||||
|
Sorry, we do not accept changes directly against this repository. Please see
|
||||||
|
CONTRIBUTING.md for information on where and how to contribute instead.
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"controller.go",
|
|
||||||
"main.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller",
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
|
||||||
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
|
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/listers/apps/v1beta2:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/util/workqueue:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/signals:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_binary(
|
|
||||||
name = "sample-controller",
|
|
||||||
importpath = "k8s.io/sample-controller",
|
|
||||||
library = ":go_default_library",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/signals:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Contributing guidelines
|
||||||
|
|
||||||
|
Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes.
|
||||||
|
|
||||||
|
This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/sample-controller](https://git.k8s.io/kubernetes/staging/src/k8s.io/sample-controller) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot).
|
||||||
|
|
||||||
|
Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/staging.md) for more information
|
||||||
Generated
+370
-282
File diff suppressed because it is too large
Load Diff
Generated
+2
@@ -0,0 +1,2 @@
|
|||||||
|
approvers:
|
||||||
|
- dep-approvers
|
||||||
@@ -23,12 +23,21 @@ Changes should not be made to these files manually, and when creating your own
|
|||||||
controller based off of this implementation you should not copy these files and
|
controller based off of this implementation you should not copy these files and
|
||||||
instead run the `update-codegen` script to generate your own.
|
instead run the `update-codegen` script to generate your own.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
The sample controller uses [client-go library](https://github.com/kubernetes/client-go/tree/master/tools/cache) extensively.
|
||||||
|
The details of interaction points of the sample controller with various mechanisms from this library are
|
||||||
|
explained [here](docs/controller-client-go.md).
|
||||||
|
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
This is an example of how to build a kube-like controller with a single type.
|
This is an example of how to build a kube-like controller with a single type.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
|
**Prerequisite**: Since the sample-controller uses `apps/v1` deployments, the Kubernetes cluster version should be greater than 1.9.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# assumes you have a working kubeconfig, not required if operating in-cluster
|
# assumes you have a working kubeconfig, not required if operating in-cluster
|
||||||
$ go run *.go -kubeconfig=$HOME/.kube/config
|
$ go run *.go -kubeconfig=$HOME/.kube/config
|
||||||
@@ -73,6 +82,49 @@ type User struct {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
To validate custom resources, use the [`CustomResourceValidation`](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#validation) feature.
|
||||||
|
|
||||||
|
This feature is beta and enabled by default in v1.9.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The schema in [`crd-validation.yaml`](./artifacts/examples/crd-validation.yaml) applies the following validation on the custom resource:
|
||||||
|
`spec.replicas` must be an integer and must have a minimum value of 1 and a maximum value of 10.
|
||||||
|
|
||||||
|
In the above steps, use `crd-validation.yaml` to create the CRD:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# create a CustomResourceDefinition supporting validation
|
||||||
|
$ kubectl create -f artifacts/examples/crd-validation.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subresources
|
||||||
|
|
||||||
|
Custom Resources support `/status` and `/scale` subresources as an
|
||||||
|
[alpha feature](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#subresources) in v1.10.
|
||||||
|
Enable this feature using the `CustomResourceSubresources` feature gate on the [kube-apiserver](https://kubernetes.io/docs/admin/kube-apiserver):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
--feature-gates=CustomResourceSubresources=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The CRD in [`crd-status-subresource.yaml`](./artifacts/examples/crd-status-subresource.yaml) enables the `/status` subresource
|
||||||
|
for custom resources.
|
||||||
|
This means that [`UpdateStatus`](./controller.go#L330) can be used by the controller to update only the status part of the custom resource.
|
||||||
|
|
||||||
|
To understand why only the status part of the custom resource should be updated, please refer to the [Kubernetes API conventions](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status).
|
||||||
|
|
||||||
|
In the above steps, use `crd-status-subresource.yaml` to create the CRD:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# create a CustomResourceDefinition supporting the status subresource
|
||||||
|
$ kubectl create -f artifacts/examples/crd-status-subresource.yaml
|
||||||
|
```
|
||||||
|
|
||||||
## Cleanup
|
## Cleanup
|
||||||
|
|
||||||
You can clean up the created CustomResourceDefinition with:
|
You can clean up the created CustomResourceDefinition with:
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Defined below are the security contacts for this repo.
|
||||||
|
#
|
||||||
|
# They are the contact point for the Product Security Team to reach out
|
||||||
|
# to for triaging and handling of incoming issues.
|
||||||
|
#
|
||||||
|
# The below names agree to abide by the
|
||||||
|
# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
|
||||||
|
# and will be removed and replaced if they violate that agreement.
|
||||||
|
#
|
||||||
|
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||||
|
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||||
|
|
||||||
|
cjcullen
|
||||||
|
jessfraz
|
||||||
|
liggitt
|
||||||
|
philips
|
||||||
|
tallclair
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: foos.samplecontroller.k8s.io
|
||||||
|
spec:
|
||||||
|
group: samplecontroller.k8s.io
|
||||||
|
version: v1alpha1
|
||||||
|
names:
|
||||||
|
kind: Foo
|
||||||
|
plural: foos
|
||||||
|
scope: Namespaced
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: foos.samplecontroller.k8s.io
|
||||||
|
spec:
|
||||||
|
group: samplecontroller.k8s.io
|
||||||
|
version: v1alpha1
|
||||||
|
names:
|
||||||
|
kind: Foo
|
||||||
|
plural: foos
|
||||||
|
scope: Namespaced
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
properties:
|
||||||
|
spec:
|
||||||
|
properties:
|
||||||
|
replicas:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maximum: 10
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Kubernetes Community Code of Conduct
|
||||||
|
|
||||||
|
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
||||||
+19
-24
@@ -21,18 +21,18 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
kubeinformers "k8s.io/client-go/informers"
|
appsinformers "k8s.io/client-go/informers/apps/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
appslisters "k8s.io/client-go/listers/apps/v1beta2"
|
appslisters "k8s.io/client-go/listers/apps/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
@@ -40,7 +40,7 @@ import (
|
|||||||
samplev1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1"
|
samplev1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1"
|
||||||
clientset "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
clientset "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||||
samplescheme "k8s.io/sample-controller/pkg/client/clientset/versioned/scheme"
|
samplescheme "k8s.io/sample-controller/pkg/client/clientset/versioned/scheme"
|
||||||
informers "k8s.io/sample-controller/pkg/client/informers/externalversions"
|
informers "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1"
|
||||||
listers "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1"
|
listers "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,13 +88,8 @@ type Controller struct {
|
|||||||
func NewController(
|
func NewController(
|
||||||
kubeclientset kubernetes.Interface,
|
kubeclientset kubernetes.Interface,
|
||||||
sampleclientset clientset.Interface,
|
sampleclientset clientset.Interface,
|
||||||
kubeInformerFactory kubeinformers.SharedInformerFactory,
|
deploymentInformer appsinformers.DeploymentInformer,
|
||||||
sampleInformerFactory informers.SharedInformerFactory) *Controller {
|
fooInformer informers.FooInformer) *Controller {
|
||||||
|
|
||||||
// obtain references to shared index informers for the Deployment and Foo
|
|
||||||
// types.
|
|
||||||
deploymentInformer := kubeInformerFactory.Apps().V1beta2().Deployments()
|
|
||||||
fooInformer := sampleInformerFactory.Samplecontroller().V1alpha1().Foos()
|
|
||||||
|
|
||||||
// Create event broadcaster
|
// Create event broadcaster
|
||||||
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
||||||
@@ -134,8 +129,8 @@ func NewController(
|
|||||||
deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: controller.handleObject,
|
AddFunc: controller.handleObject,
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
newDepl := new.(*appsv1beta2.Deployment)
|
newDepl := new.(*appsv1.Deployment)
|
||||||
oldDepl := old.(*appsv1beta2.Deployment)
|
oldDepl := old.(*appsv1.Deployment)
|
||||||
if newDepl.ResourceVersion == oldDepl.ResourceVersion {
|
if newDepl.ResourceVersion == oldDepl.ResourceVersion {
|
||||||
// Periodic resync will send update events for all known Deployments.
|
// Periodic resync will send update events for all known Deployments.
|
||||||
// Two different versions of the same Deployment will always have different RVs.
|
// Two different versions of the same Deployment will always have different RVs.
|
||||||
@@ -277,7 +272,7 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
deployment, err := c.deploymentsLister.Deployments(foo.Namespace).Get(deploymentName)
|
deployment, err := c.deploymentsLister.Deployments(foo.Namespace).Get(deploymentName)
|
||||||
// If the resource doesn't exist, we'll create it
|
// If the resource doesn't exist, we'll create it
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
deployment, err = c.kubeclientset.AppsV1beta2().Deployments(foo.Namespace).Create(newDeployment(foo))
|
deployment, err = c.kubeclientset.AppsV1().Deployments(foo.Namespace).Create(newDeployment(foo))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an error occurs during Get/Create, we'll requeue the item so we can
|
// If an error occurs during Get/Create, we'll requeue the item so we can
|
||||||
@@ -299,8 +294,8 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
// number does not equal the current desired replicas on the Deployment, we
|
// number does not equal the current desired replicas on the Deployment, we
|
||||||
// should update the Deployment resource.
|
// should update the Deployment resource.
|
||||||
if foo.Spec.Replicas != nil && *foo.Spec.Replicas != *deployment.Spec.Replicas {
|
if foo.Spec.Replicas != nil && *foo.Spec.Replicas != *deployment.Spec.Replicas {
|
||||||
glog.V(4).Infof("Foor: %d, deplR: %d", *foo.Spec.Replicas, *deployment.Spec.Replicas)
|
glog.V(4).Infof("Foo %s replicas: %d, deployment replicas: %d", name, *foo.Spec.Replicas, *deployment.Spec.Replicas)
|
||||||
deployment, err = c.kubeclientset.AppsV1beta2().Deployments(foo.Namespace).Update(newDeployment(foo))
|
deployment, err = c.kubeclientset.AppsV1().Deployments(foo.Namespace).Update(newDeployment(foo))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an error occurs during Update, we'll requeue the item so we can
|
// If an error occurs during Update, we'll requeue the item so we can
|
||||||
@@ -321,16 +316,16 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) updateFooStatus(foo *samplev1alpha1.Foo, deployment *appsv1beta2.Deployment) error {
|
func (c *Controller) updateFooStatus(foo *samplev1alpha1.Foo, deployment *appsv1.Deployment) error {
|
||||||
// NEVER modify objects from the store. It's a read-only, local cache.
|
// NEVER modify objects from the store. It's a read-only, local cache.
|
||||||
// You can use DeepCopy() to make a deep copy of original object and modify this copy
|
// You can use DeepCopy() to make a deep copy of original object and modify this copy
|
||||||
// Or create a copy manually for better performance
|
// Or create a copy manually for better performance
|
||||||
fooCopy := foo.DeepCopy()
|
fooCopy := foo.DeepCopy()
|
||||||
fooCopy.Status.AvailableReplicas = deployment.Status.AvailableReplicas
|
fooCopy.Status.AvailableReplicas = deployment.Status.AvailableReplicas
|
||||||
// Until #38113 is merged, we must use Update instead of UpdateStatus to
|
// If the CustomResourceSubresources feature gate is not enabled,
|
||||||
// update the Status block of the Foo resource. UpdateStatus will not
|
// we must use Update instead of UpdateStatus to update the Status block of the Foo resource.
|
||||||
// allow changes to the Spec of the resource, which is ideal for ensuring
|
// UpdateStatus will not allow changes to the Spec of the resource,
|
||||||
// nothing other than resource status has been updated.
|
// which is ideal for ensuring nothing other than resource status has been updated.
|
||||||
_, err := c.sampleclientset.SamplecontrollerV1alpha1().Foos(foo.Namespace).Update(fooCopy)
|
_, err := c.sampleclientset.SamplecontrollerV1alpha1().Foos(foo.Namespace).Update(fooCopy)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -391,12 +386,12 @@ func (c *Controller) handleObject(obj interface{}) {
|
|||||||
// newDeployment creates a new Deployment for a Foo resource. It also sets
|
// newDeployment creates a new Deployment for a Foo resource. It also sets
|
||||||
// the appropriate OwnerReferences on the resource so handleObject can discover
|
// the appropriate OwnerReferences on the resource so handleObject can discover
|
||||||
// the Foo resource that 'owns' it.
|
// the Foo resource that 'owns' it.
|
||||||
func newDeployment(foo *samplev1alpha1.Foo) *appsv1beta2.Deployment {
|
func newDeployment(foo *samplev1alpha1.Foo) *appsv1.Deployment {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"app": "nginx",
|
"app": "nginx",
|
||||||
"controller": foo.Name,
|
"controller": foo.Name,
|
||||||
}
|
}
|
||||||
return &appsv1beta2.Deployment{
|
return &appsv1.Deployment{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: foo.Spec.DeploymentName,
|
Name: foo.Spec.DeploymentName,
|
||||||
Namespace: foo.Namespace,
|
Namespace: foo.Namespace,
|
||||||
@@ -408,7 +403,7 @@ func newDeployment(foo *samplev1alpha1.Foo) *appsv1beta2.Deployment {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: appsv1beta2.DeploymentSpec{
|
Spec: appsv1.DeploymentSpec{
|
||||||
Replicas: foo.Spec.Replicas,
|
Replicas: foo.Spec.Replicas,
|
||||||
Selector: &metav1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: labels,
|
MatchLabels: labels,
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
apps "k8s.io/api/apps/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
|
kubeinformers "k8s.io/client-go/informers"
|
||||||
|
k8sfake "k8s.io/client-go/kubernetes/fake"
|
||||||
|
core "k8s.io/client-go/testing"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
"k8s.io/client-go/tools/record"
|
||||||
|
|
||||||
|
samplecontroller "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1"
|
||||||
|
"k8s.io/sample-controller/pkg/client/clientset/versioned/fake"
|
||||||
|
informers "k8s.io/sample-controller/pkg/client/informers/externalversions"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
alwaysReady = func() bool { return true }
|
||||||
|
noResyncPeriodFunc = func() time.Duration { return 0 }
|
||||||
|
)
|
||||||
|
|
||||||
|
type fixture struct {
|
||||||
|
t *testing.T
|
||||||
|
|
||||||
|
client *fake.Clientset
|
||||||
|
kubeclient *k8sfake.Clientset
|
||||||
|
// Objects to put in the store.
|
||||||
|
fooLister []*samplecontroller.Foo
|
||||||
|
deploymentLister []*apps.Deployment
|
||||||
|
// Actions expected to happen on the client.
|
||||||
|
kubeactions []core.Action
|
||||||
|
actions []core.Action
|
||||||
|
// Objects from here preloaded into NewSimpleFake.
|
||||||
|
kubeobjects []runtime.Object
|
||||||
|
objects []runtime.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFixture(t *testing.T) *fixture {
|
||||||
|
f := &fixture{}
|
||||||
|
f.t = t
|
||||||
|
f.objects = []runtime.Object{}
|
||||||
|
f.kubeobjects = []runtime.Object{}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFoo(name string, replicas *int32) *samplecontroller.Foo {
|
||||||
|
return &samplecontroller.Foo{
|
||||||
|
TypeMeta: metav1.TypeMeta{APIVersion: samplecontroller.SchemeGroupVersion.String()},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
},
|
||||||
|
Spec: samplecontroller.FooSpec{
|
||||||
|
DeploymentName: fmt.Sprintf("%s-deployment", name),
|
||||||
|
Replicas: replicas,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) newController() (*Controller, informers.SharedInformerFactory, kubeinformers.SharedInformerFactory) {
|
||||||
|
f.client = fake.NewSimpleClientset(f.objects...)
|
||||||
|
f.kubeclient = k8sfake.NewSimpleClientset(f.kubeobjects...)
|
||||||
|
|
||||||
|
i := informers.NewSharedInformerFactory(f.client, noResyncPeriodFunc())
|
||||||
|
k8sI := kubeinformers.NewSharedInformerFactory(f.kubeclient, noResyncPeriodFunc())
|
||||||
|
|
||||||
|
c := NewController(f.kubeclient, f.client,
|
||||||
|
k8sI.Apps().V1().Deployments(), i.Samplecontroller().V1alpha1().Foos())
|
||||||
|
|
||||||
|
c.foosSynced = alwaysReady
|
||||||
|
c.deploymentsSynced = alwaysReady
|
||||||
|
c.recorder = &record.FakeRecorder{}
|
||||||
|
|
||||||
|
for _, f := range f.fooLister {
|
||||||
|
i.Samplecontroller().V1alpha1().Foos().Informer().GetIndexer().Add(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range f.deploymentLister {
|
||||||
|
k8sI.Apps().V1().Deployments().Informer().GetIndexer().Add(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, i, k8sI
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) run(fooName string) {
|
||||||
|
f.runController(fooName, true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) runExpectError(fooName string) {
|
||||||
|
f.runController(fooName, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) runController(fooName string, startInformers bool, expectError bool) {
|
||||||
|
c, i, k8sI := f.newController()
|
||||||
|
if startInformers {
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
defer close(stopCh)
|
||||||
|
i.Start(stopCh)
|
||||||
|
k8sI.Start(stopCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.syncHandler(fooName)
|
||||||
|
if !expectError && err != nil {
|
||||||
|
f.t.Errorf("error syncing foo: %v", err)
|
||||||
|
} else if expectError && err == nil {
|
||||||
|
f.t.Error("expected error syncing foo, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
actions := filterInformerActions(f.client.Actions())
|
||||||
|
for i, action := range actions {
|
||||||
|
if len(f.actions) < i+1 {
|
||||||
|
f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedAction := f.actions[i]
|
||||||
|
checkAction(expectedAction, action, f.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(f.actions) > len(actions) {
|
||||||
|
f.t.Errorf("%d additional expected actions:%+v", len(f.actions)-len(actions), f.actions[len(actions):])
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
||||||
|
for i, action := range k8sActions {
|
||||||
|
if len(f.kubeactions) < i+1 {
|
||||||
|
f.t.Errorf("%d unexpected actions: %+v", len(k8sActions)-len(f.kubeactions), k8sActions[i:])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedAction := f.kubeactions[i]
|
||||||
|
checkAction(expectedAction, action, f.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(f.kubeactions) > len(k8sActions) {
|
||||||
|
f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkAction verifies that expected and actual actions are equal and both have
|
||||||
|
// same attached resources
|
||||||
|
func checkAction(expected, actual core.Action, t *testing.T) {
|
||||||
|
if !(expected.Matches(actual.GetVerb(), actual.GetResource().Resource) && actual.GetSubresource() == expected.GetSubresource()) {
|
||||||
|
t.Errorf("Expected\n\t%#v\ngot\n\t%#v", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
|
||||||
|
t.Errorf("Action has wrong type. Expected: %t. Got: %t", expected, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch a := actual.(type) {
|
||||||
|
case core.CreateAction:
|
||||||
|
e, _ := expected.(core.CreateAction)
|
||||||
|
expObject := e.GetObject()
|
||||||
|
object := a.GetObject()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expObject, object) {
|
||||||
|
t.Errorf("Action %s %s has wrong object\nDiff:\n %s",
|
||||||
|
a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expObject, object))
|
||||||
|
}
|
||||||
|
case core.UpdateAction:
|
||||||
|
e, _ := expected.(core.UpdateAction)
|
||||||
|
expObject := e.GetObject()
|
||||||
|
object := a.GetObject()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expObject, object) {
|
||||||
|
t.Errorf("Action %s %s has wrong object\nDiff:\n %s",
|
||||||
|
a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expObject, object))
|
||||||
|
}
|
||||||
|
case core.PatchAction:
|
||||||
|
e, _ := expected.(core.PatchAction)
|
||||||
|
expPatch := e.GetPatch()
|
||||||
|
patch := a.GetPatch()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expPatch, expPatch) {
|
||||||
|
t.Errorf("Action %s %s has wrong patch\nDiff:\n %s",
|
||||||
|
a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintDiff(expPatch, patch))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterInformerActions filters list and watch actions for testing resources.
|
||||||
|
// Since list and watch don't change resource state we can filter it to lower
|
||||||
|
// nose level in our tests.
|
||||||
|
func filterInformerActions(actions []core.Action) []core.Action {
|
||||||
|
ret := []core.Action{}
|
||||||
|
for _, action := range actions {
|
||||||
|
if len(action.GetNamespace()) == 0 &&
|
||||||
|
(action.Matches("list", "foos") ||
|
||||||
|
action.Matches("watch", "foos") ||
|
||||||
|
action.Matches("list", "deployments") ||
|
||||||
|
action.Matches("watch", "deployments")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) expectCreateDeploymentAction(d *apps.Deployment) {
|
||||||
|
f.kubeactions = append(f.kubeactions, core.NewCreateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) expectUpdateDeploymentAction(d *apps.Deployment) {
|
||||||
|
f.kubeactions = append(f.kubeactions, core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixture) expectUpdateFooStatusAction(foo *samplecontroller.Foo) {
|
||||||
|
action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "foos"}, foo.Namespace, foo)
|
||||||
|
// TODO: Until #38113 is merged, we can't use Subresource
|
||||||
|
//action.Subresource = "status"
|
||||||
|
f.actions = append(f.actions, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKey(foo *samplecontroller.Foo, t *testing.T) string {
|
||||||
|
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(foo)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error getting key for foo %v: %v", foo.Name, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatesDeployment(t *testing.T) {
|
||||||
|
f := newFixture(t)
|
||||||
|
foo := newFoo("test", int32Ptr(1))
|
||||||
|
|
||||||
|
f.fooLister = append(f.fooLister, foo)
|
||||||
|
f.objects = append(f.objects, foo)
|
||||||
|
|
||||||
|
expDeployment := newDeployment(foo)
|
||||||
|
f.expectCreateDeploymentAction(expDeployment)
|
||||||
|
f.expectUpdateFooStatusAction(foo)
|
||||||
|
|
||||||
|
f.run(getKey(foo, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoNothing(t *testing.T) {
|
||||||
|
f := newFixture(t)
|
||||||
|
foo := newFoo("test", int32Ptr(1))
|
||||||
|
d := newDeployment(foo)
|
||||||
|
|
||||||
|
f.fooLister = append(f.fooLister, foo)
|
||||||
|
f.objects = append(f.objects, foo)
|
||||||
|
f.deploymentLister = append(f.deploymentLister, d)
|
||||||
|
f.kubeobjects = append(f.kubeobjects, d)
|
||||||
|
|
||||||
|
f.expectUpdateFooStatusAction(foo)
|
||||||
|
f.run(getKey(foo, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateDeployment(t *testing.T) {
|
||||||
|
f := newFixture(t)
|
||||||
|
foo := newFoo("test", int32Ptr(1))
|
||||||
|
d := newDeployment(foo)
|
||||||
|
|
||||||
|
// Update replicas
|
||||||
|
foo.Spec.Replicas = int32Ptr(2)
|
||||||
|
expDeployment := newDeployment(foo)
|
||||||
|
|
||||||
|
f.fooLister = append(f.fooLister, foo)
|
||||||
|
f.objects = append(f.objects, foo)
|
||||||
|
f.deploymentLister = append(f.deploymentLister, d)
|
||||||
|
f.kubeobjects = append(f.kubeobjects, d)
|
||||||
|
|
||||||
|
f.expectUpdateFooStatusAction(foo)
|
||||||
|
f.expectUpdateDeploymentAction(expDeployment)
|
||||||
|
f.run(getKey(foo, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotControlledByUs(t *testing.T) {
|
||||||
|
f := newFixture(t)
|
||||||
|
foo := newFoo("test", int32Ptr(1))
|
||||||
|
d := newDeployment(foo)
|
||||||
|
|
||||||
|
d.ObjectMeta.OwnerReferences = []metav1.OwnerReference{}
|
||||||
|
|
||||||
|
f.fooLister = append(f.fooLister, foo)
|
||||||
|
f.objects = append(f.objects, foo)
|
||||||
|
f.deploymentLister = append(f.deploymentLister, d)
|
||||||
|
f.kubeobjects = append(f.kubeobjects, d)
|
||||||
|
|
||||||
|
f.runExpectError(getKey(foo, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func int32Ptr(i int32) *int32 { return &i }
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# client-go under the hood
|
||||||
|
|
||||||
|
The [client-go](https://github.com/kubernetes/client-go/) library contains various mechanisms that you can use when
|
||||||
|
developing your custom controllers. These mechanisms are defined in the
|
||||||
|
[tools/cache folder](https://github.com/kubernetes/client-go/tree/master/tools/cache) of the library.
|
||||||
|
|
||||||
|
Here is a pictorial representation showing how the various components in
|
||||||
|
the client-go library work and their interaction points with the custom
|
||||||
|
controller code that you will write.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="images/client-go-controller-interaction.jpeg" height="600" width="700"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## client-go components
|
||||||
|
|
||||||
|
* Reflector: A reflector, which is defined in [type *Reflector* inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/reflector.go),
|
||||||
|
watches the Kubernetes API for the specified resource type (kind).
|
||||||
|
The function in which this is done is *ListAndWatch*.
|
||||||
|
The watch could be for an in-built resource or it could be for a custom resource.
|
||||||
|
When the reflector receives notification about existence of new
|
||||||
|
resource instance through the watch API, it gets the newly created object
|
||||||
|
using the corresponding listing API and puts it in the Delta Fifo queue
|
||||||
|
inside the *watchHandler* function.
|
||||||
|
|
||||||
|
|
||||||
|
* Informer: An informer defined in the [base controller inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/controller.go) pops objects from the Delta Fifo queue.
|
||||||
|
The function in which this is done is *processLoop*. The job of this base controller
|
||||||
|
is to save the object for later retrieval, and to invoke our controller passing it the object.
|
||||||
|
|
||||||
|
* Indexer: An indexer provides indexing functionality over objects.
|
||||||
|
It is defined in [type *Indexer* inside package *cache*](https://github.com/kubernetes/client-go/blob/master/tools/cache/index.go). A typical indexing use-case is to create an index based on object labels. Indexer can
|
||||||
|
maintain indexes based on several indexing functions.
|
||||||
|
Indexer uses a thread-safe data store to store objects and their keys.
|
||||||
|
There is a default function named *MetaNamespaceKeyFunc* defined in [type Store inside package cache](https://github.com/kubernetes/client-go/blob/master/tools/cache/store.go)
|
||||||
|
that generates an object’s key as `<namespace>/<name>` combination for that object.
|
||||||
|
|
||||||
|
|
||||||
|
## Custom Controller components
|
||||||
|
|
||||||
|
* Informer reference: This is the reference to the Informer instance that knows
|
||||||
|
how to work with your custom resource objects. Your custom controller code needs
|
||||||
|
to create the appropriate Informer.
|
||||||
|
|
||||||
|
* Indexer reference: This is the reference to the Indexer instance that knows
|
||||||
|
how to work with your custom resource objects. Your custom controller code needs
|
||||||
|
to create this. You will be using this reference for retrieving objects for
|
||||||
|
later processing.
|
||||||
|
|
||||||
|
The base controller in client-go provides the *NewIndexerInformer* function to create Informer and Indexer.
|
||||||
|
In your code you can either [directly invoke this function](https://github.com/kubernetes/client-go/blob/master/examples/workqueue/main.go#L174) or [use factory methods for creating an informer.](https://github.com/kubernetes/sample-controller/blob/master/main.go#L61)
|
||||||
|
|
||||||
|
* Resource Event Handlers: These are the callback functions which will be called by
|
||||||
|
the Informer when it wants to deliver an object to your controller. The typical
|
||||||
|
pattern to write these functions is to obtain the dispatched object’s key
|
||||||
|
and enqueue that key in a work queue for further processing.
|
||||||
|
|
||||||
|
* Work queue: This is the queue that you create in your controller code to decouple
|
||||||
|
delivery of an object from its processing. Resource event handler functions are written
|
||||||
|
to extract the delivered object’s key and add that to the work queue.
|
||||||
|
|
||||||
|
* Process Item: This is the function that you create in your code which processes items
|
||||||
|
from the work queue. There can be one or more other functions that do the actual processing.
|
||||||
|
These functions will typically use the [Indexer reference](https://github.com/kubernetes/client-go/blob/master/examples/workqueue/main.go#L73), or a Listing wrapper to retrieve the object corresponding to the key.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright 2017 The Kubernetes Authors.
|
# Copyright 2017 The Kubernetes Authors.
|
||||||
#
|
#
|
||||||
@@ -28,7 +28,8 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge
|
|||||||
${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
|
${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
|
||||||
k8s.io/sample-controller/pkg/client k8s.io/sample-controller/pkg/apis \
|
k8s.io/sample-controller/pkg/client k8s.io/sample-controller/pkg/apis \
|
||||||
samplecontroller:v1alpha1 \
|
samplecontroller:v1alpha1 \
|
||||||
--output-base "$(dirname ${BASH_SOURCE})/../../.."
|
--output-base "$(dirname ${BASH_SOURCE})/../../.." \
|
||||||
|
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
|
||||||
|
|
||||||
# To use your own boilerplate text append:
|
# To use your own boilerplate text use:
|
||||||
# --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt
|
# --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright 2017 The Kubernetes Authors.
|
# Copyright 2017 The Kubernetes Authors.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ func main() {
|
|||||||
kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30)
|
kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30)
|
||||||
exampleInformerFactory := informers.NewSharedInformerFactory(exampleClient, time.Second*30)
|
exampleInformerFactory := informers.NewSharedInformerFactory(exampleClient, time.Second*30)
|
||||||
|
|
||||||
controller := NewController(kubeClient, exampleClient, kubeInformerFactory, exampleInformerFactory)
|
controller := NewController(kubeClient, exampleClient,
|
||||||
|
kubeInformerFactory.Apps().V1().Deployments(),
|
||||||
|
exampleInformerFactory.Samplecontroller().V1alpha1().Foos())
|
||||||
|
|
||||||
go kubeInformerFactory.Start(stopCh)
|
go kubeInformerFactory.Start(stopCh)
|
||||||
go exampleInformerFactory.Start(stopCh)
|
go exampleInformerFactory.Start(stopCh)
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["register.go"],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/apis/samplecontroller",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"doc.go",
|
|
||||||
"register.go",
|
|
||||||
"types.go",
|
|
||||||
"zz_generated.deepcopy.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
@@ -47,5 +48,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||||||
&Foo{},
|
&Foo{},
|
||||||
&FooList{},
|
&FooList{},
|
||||||
)
|
)
|
||||||
|
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// +genclient
|
// +genclient
|
||||||
// +genclient:noStatus
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// Foo is a specification for a Foo resource
|
// Foo is a specification for a Foo resource
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
@@ -48,9 +48,8 @@ func (in *Foo) DeepCopy() *Foo {
|
|||||||
func (in *Foo) DeepCopyObject() runtime.Object {
|
func (in *Foo) DeepCopyObject() runtime.Object {
|
||||||
if c := in.DeepCopy(); c != nil {
|
if c := in.DeepCopy(); c != nil {
|
||||||
return c
|
return c
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
@@ -82,9 +81,8 @@ func (in *FooList) DeepCopy() *FooList {
|
|||||||
func (in *FooList) DeepCopyObject() runtime.Object {
|
func (in *FooList) DeepCopyObject() runtime.Object {
|
||||||
if c := in.DeepCopy(); c != nil {
|
if c := in.DeepCopy(); c != nil {
|
||||||
return c
|
return c
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"clientset.go",
|
|
||||||
"doc.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/fake:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,10 +14,11 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package versioned
|
package versioned
|
||||||
|
|
||||||
import (
|
import (
|
||||||
glog "github.com/golang/glog"
|
|
||||||
discovery "k8s.io/client-go/discovery"
|
discovery "k8s.io/client-go/discovery"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||||
@@ -72,7 +73,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
|
|||||||
|
|
||||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("failed to create the DiscoveryClient: %v", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &cs, nil
|
return &cs, nil
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
// This package has the automatically generated clientset.
|
// This package has the automatically generated clientset.
|
||||||
package versioned
|
package versioned
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"clientset_generated.go",
|
|
||||||
"doc.go",
|
|
||||||
"register.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned/fake",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/discovery/fake:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -39,11 +41,20 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fakePtr := testing.Fake{}
|
cs := &Clientset{}
|
||||||
fakePtr.AddReactor("*", "*", testing.ObjectReaction(o))
|
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||||
fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))
|
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||||
|
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||||
|
gvr := action.GetResource()
|
||||||
|
ns := action.GetNamespace()
|
||||||
|
watch, err := o.Watch(gvr, ns)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
return true, watch, nil
|
||||||
|
})
|
||||||
|
|
||||||
return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}}
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
// This package has the automatically generated fake clientset.
|
// This package has the automatically generated fake clientset.
|
||||||
package fake
|
package fake
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -38,7 +40,7 @@ func init() {
|
|||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "k8s.io/client-go/kubernetes"
|
// "k8s.io/client-go/kubernetes"
|
||||||
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
@@ -49,5 +51,4 @@ func init() {
|
|||||||
// correctly.
|
// correctly.
|
||||||
func AddToScheme(scheme *runtime.Scheme) {
|
func AddToScheme(scheme *runtime.Scheme) {
|
||||||
samplecontrollerv1alpha1.AddToScheme(scheme)
|
samplecontrollerv1alpha1.AddToScheme(scheme)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"doc.go",
|
|
||||||
"register.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned/scheme",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
// This package contains the scheme of the automatically generated clientset.
|
// This package contains the scheme of the automatically generated clientset.
|
||||||
package scheme
|
package scheme
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package scheme
|
package scheme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -38,7 +40,7 @@ func init() {
|
|||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "k8s.io/client-go/kubernetes"
|
// "k8s.io/client-go/kubernetes"
|
||||||
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
@@ -49,5 +51,4 @@ func init() {
|
|||||||
// correctly.
|
// correctly.
|
||||||
func AddToScheme(scheme *runtime.Scheme) {
|
func AddToScheme(scheme *runtime.Scheme) {
|
||||||
samplecontrollerv1alpha1.AddToScheme(scheme)
|
samplecontrollerv1alpha1.AddToScheme(scheme)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"doc.go",
|
|
||||||
"foo.go",
|
|
||||||
"generated_expansion.go",
|
|
||||||
"samplecontroller_client.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/scheme:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
// This package has the automatically generated typed clients.
|
// This package has the automatically generated typed clients.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"doc.go",
|
|
||||||
"fake_foo.go",
|
|
||||||
"fake_samplecontroller_client.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1/fake",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned/typed/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
// Package fake has the automatically generated clients.
|
// Package fake has the automatically generated clients.
|
||||||
package fake
|
package fake
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -60,7 +62,7 @@ func (c *FakeFoos) List(opts v1.ListOptions) (result *v1alpha1.FooList, err erro
|
|||||||
if label == nil {
|
if label == nil {
|
||||||
label = labels.Everything()
|
label = labels.Everything()
|
||||||
}
|
}
|
||||||
list := &v1alpha1.FooList{}
|
list := &v1alpha1.FooList{ListMeta: obj.(*v1alpha1.FooList).ListMeta}
|
||||||
for _, item := range obj.(*v1alpha1.FooList).Items {
|
for _, item := range obj.(*v1alpha1.FooList).Items {
|
||||||
if label.Matches(labels.Set(item.Labels)) {
|
if label.Matches(labels.Set(item.Labels)) {
|
||||||
list.Items = append(list.Items, item)
|
list.Items = append(list.Items, item)
|
||||||
@@ -98,6 +100,18 @@ func (c *FakeFoos) Update(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) {
|
|||||||
return obj.(*v1alpha1.Foo), err
|
return obj.(*v1alpha1.Foo), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateStatus was generated because the type contains a Status member.
|
||||||
|
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||||
|
func (c *FakeFoos) UpdateStatus(foo *v1alpha1.Foo) (*v1alpha1.Foo, error) {
|
||||||
|
obj, err := c.Fake.
|
||||||
|
Invokes(testing.NewUpdateSubresourceAction(foosResource, "status", c.ns, foo), &v1alpha1.Foo{})
|
||||||
|
|
||||||
|
if obj == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.(*v1alpha1.Foo), err
|
||||||
|
}
|
||||||
|
|
||||||
// Delete takes name of the foo and deletes it. Returns an error if one occurs.
|
// Delete takes name of the foo and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeFoos) Delete(name string, options *v1.DeleteOptions) error {
|
func (c *FakeFoos) Delete(name string, options *v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -35,6 +37,7 @@ type FoosGetter interface {
|
|||||||
type FooInterface interface {
|
type FooInterface interface {
|
||||||
Create(*v1alpha1.Foo) (*v1alpha1.Foo, error)
|
Create(*v1alpha1.Foo) (*v1alpha1.Foo, error)
|
||||||
Update(*v1alpha1.Foo) (*v1alpha1.Foo, error)
|
Update(*v1alpha1.Foo) (*v1alpha1.Foo, error)
|
||||||
|
UpdateStatus(*v1alpha1.Foo) (*v1alpha1.Foo, error)
|
||||||
Delete(name string, options *v1.DeleteOptions) error
|
Delete(name string, options *v1.DeleteOptions) error
|
||||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||||
Get(name string, options v1.GetOptions) (*v1alpha1.Foo, error)
|
Get(name string, options v1.GetOptions) (*v1alpha1.Foo, error)
|
||||||
@@ -118,6 +121,22 @@ func (c *foos) Update(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateStatus was generated because the type contains a Status member.
|
||||||
|
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||||
|
|
||||||
|
func (c *foos) UpdateStatus(foo *v1alpha1.Foo) (result *v1alpha1.Foo, err error) {
|
||||||
|
result = &v1alpha1.Foo{}
|
||||||
|
err = c.client.Put().
|
||||||
|
Namespace(c.ns).
|
||||||
|
Resource("foos").
|
||||||
|
Name(foo.Name).
|
||||||
|
SubResource("status").
|
||||||
|
Body(foo).
|
||||||
|
Do().
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Delete takes name of the foo and deletes it. Returns an error if one occurs.
|
// Delete takes name of the foo and deletes it. Returns an error if one occurs.
|
||||||
func (c *foos) Delete(name string, options *v1.DeleteOptions) error {
|
func (c *foos) Delete(name string, options *v1.DeleteOptions) error {
|
||||||
return c.client.Delete().
|
return c.client.Delete().
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
type FooExpansion interface{}
|
type FooExpansion interface{}
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"factory.go",
|
|
||||||
"generic.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/informers/externalversions",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces:all-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,11 +14,15 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package externalversions
|
package externalversions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@@ -26,17 +30,18 @@ import (
|
|||||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||||
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
||||||
samplecontroller "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller"
|
samplecontroller "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller"
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
time "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||||
|
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||||
|
|
||||||
type sharedInformerFactory struct {
|
type sharedInformerFactory struct {
|
||||||
client versioned.Interface
|
client versioned.Interface
|
||||||
namespace string
|
namespace string
|
||||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
defaultResync time.Duration
|
defaultResync time.Duration
|
||||||
|
customResync map[reflect.Type]time.Duration
|
||||||
|
|
||||||
informers map[reflect.Type]cache.SharedIndexInformer
|
informers map[reflect.Type]cache.SharedIndexInformer
|
||||||
// startedInformers is used for tracking which informers have been started.
|
// startedInformers is used for tracking which informers have been started.
|
||||||
@@ -44,23 +49,62 @@ type sharedInformerFactory struct {
|
|||||||
startedInformers map[reflect.Type]bool
|
startedInformers map[reflect.Type]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory
|
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||||
|
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
for k, v := range resyncConfig {
|
||||||
|
factory.customResync[reflect.TypeOf(k)] = v
|
||||||
|
}
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||||
|
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
factory.tweakListOptions = tweakListOptions
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||||
|
func WithNamespace(namespace string) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
factory.namespace = namespace
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||||
return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil)
|
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||||
// as specified here.
|
// as specified here.
|
||||||
|
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||||
return &sharedInformerFactory{
|
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||||
|
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||||
|
factory := &sharedInformerFactory{
|
||||||
client: client,
|
client: client,
|
||||||
namespace: namespace,
|
namespace: v1.NamespaceAll,
|
||||||
tweakListOptions: tweakListOptions,
|
|
||||||
defaultResync: defaultResync,
|
defaultResync: defaultResync,
|
||||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||||
startedInformers: make(map[reflect.Type]bool),
|
startedInformers: make(map[reflect.Type]bool),
|
||||||
|
customResync: make(map[reflect.Type]time.Duration),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply all options
|
||||||
|
for _, opt := range options {
|
||||||
|
factory = opt(factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start initializes all requested informers.
|
// Start initializes all requested informers.
|
||||||
@@ -109,7 +153,13 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal
|
|||||||
if exists {
|
if exists {
|
||||||
return informer
|
return informer
|
||||||
}
|
}
|
||||||
informer = newFunc(f.client, f.defaultResync)
|
|
||||||
|
resyncPeriod, exists := f.customResync[informerType]
|
||||||
|
if !exists {
|
||||||
|
resyncPeriod = f.defaultResync
|
||||||
|
}
|
||||||
|
|
||||||
|
informer = newFunc(f.client, resyncPeriod)
|
||||||
f.informers[informerType] = informer
|
f.informers[informerType] = informer
|
||||||
|
|
||||||
return informer
|
return informer
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package externalversions
|
package externalversions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
v1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1"
|
v1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1"
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["factory_interfaces.go"],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,16 +14,17 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package internalinterfaces
|
package internalinterfaces
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
cache "k8s.io/client-go/tools/cache"
|
cache "k8s.io/client-go/tools/cache"
|
||||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||||
time "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["interface.go"],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//staging/src/k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package samplecontroller
|
package samplecontroller
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"foo.go",
|
|
||||||
"interface.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller/v1alpha1",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/clientset/versioned:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
time "time"
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
watch "k8s.io/apimachinery/pkg/watch"
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
@@ -27,7 +29,6 @@ import (
|
|||||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||||
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
||||||
v1alpha1 "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1"
|
v1alpha1 "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1"
|
||||||
time "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FooInformer provides access to a shared informer and lister for
|
// FooInformer provides access to a shared informer and lister for
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by informer-gen
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"expansion_generated.go",
|
|
||||||
"foo.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
|
||||||
"//vendor/k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by lister-gen
|
// Code generated by lister-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file was automatically generated by lister-gen
|
// Code generated by lister-gen. DO NOT EDIT.
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"signal.go",
|
|
||||||
"signal_posix.go",
|
|
||||||
] + select({
|
|
||||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
|
||||||
"signal_windows.go",
|
|
||||||
],
|
|
||||||
"//conditions:default": [],
|
|
||||||
}),
|
|
||||||
importpath = "k8s.io/sample-controller/pkg/signals",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
-900
@@ -1,900 +0,0 @@
|
|||||||
// Copyright 2015 go-swagger maintainers
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package spec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-openapi/jsonpointer"
|
|
||||||
"github.com/go-openapi/swag"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Debug enables logging when SWAGGER_DEBUG env var is not empty
|
|
||||||
Debug = os.Getenv("SWAGGER_DEBUG") != ""
|
|
||||||
)
|
|
||||||
|
|
||||||
// ExpandOptions provides options for expand.
|
|
||||||
type ExpandOptions struct {
|
|
||||||
RelativeBase string
|
|
||||||
SkipSchemas bool
|
|
||||||
ContinueOnError bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolutionCache a cache for resolving urls
|
|
||||||
type ResolutionCache interface {
|
|
||||||
Get(string) (interface{}, bool)
|
|
||||||
Set(string, interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type simpleCache struct {
|
|
||||||
lock sync.Mutex
|
|
||||||
store map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var resCache ResolutionCache
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
resCache = initResolutionCache()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initResolutionCache() ResolutionCache {
|
|
||||||
return &simpleCache{store: map[string]interface{}{
|
|
||||||
"http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(),
|
|
||||||
"http://json-schema.org/draft-04/schema": MustLoadJSONSchemaDraft04(),
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *simpleCache) Get(uri string) (interface{}, bool) {
|
|
||||||
debugLog("getting %q from resolution cache", uri)
|
|
||||||
s.lock.Lock()
|
|
||||||
v, ok := s.store[uri]
|
|
||||||
debugLog("got %q from resolution cache: %t", uri, ok)
|
|
||||||
|
|
||||||
s.lock.Unlock()
|
|
||||||
return v, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *simpleCache) Set(uri string, data interface{}) {
|
|
||||||
s.lock.Lock()
|
|
||||||
s.store[uri] = data
|
|
||||||
s.lock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveRefWithBase resolves a reference against a context root with preservation of base path
|
|
||||||
func ResolveRefWithBase(root interface{}, ref *Ref, opts *ExpandOptions) (*Schema, error) {
|
|
||||||
resolver, err := defaultSchemaLoader(root, nil, opts, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(Schema)
|
|
||||||
if err := resolver.Resolve(ref, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveRef resolves a reference against a context root
|
|
||||||
func ResolveRef(root interface{}, ref *Ref) (*Schema, error) {
|
|
||||||
return ResolveRefWithBase(root, ref, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveParameter resolves a paramter reference against a context root
|
|
||||||
func ResolveParameter(root interface{}, ref Ref) (*Parameter, error) {
|
|
||||||
return ResolveParameterWithBase(root, ref, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveParameterWithBase resolves a paramter reference against a context root and base path
|
|
||||||
func ResolveParameterWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Parameter, error) {
|
|
||||||
resolver, err := defaultSchemaLoader(root, nil, opts, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(Parameter)
|
|
||||||
if err := resolver.Resolve(&ref, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveResponse resolves response a reference against a context root
|
|
||||||
func ResolveResponse(root interface{}, ref Ref) (*Response, error) {
|
|
||||||
return ResolveResponseWithBase(root, ref, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveResponseWithBase resolves response a reference against a context root and base path
|
|
||||||
func ResolveResponseWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Response, error) {
|
|
||||||
resolver, err := defaultSchemaLoader(root, nil, opts, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(Response)
|
|
||||||
if err := resolver.Resolve(&ref, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveItems resolves header and parameter items reference against a context root and base path
|
|
||||||
func ResolveItems(root interface{}, ref Ref, opts *ExpandOptions) (*Items, error) {
|
|
||||||
resolver, err := defaultSchemaLoader(root, nil, opts, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(Items)
|
|
||||||
if err := resolver.Resolve(&ref, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolvePathItem resolves response a path item against a context root and base path
|
|
||||||
func ResolvePathItem(root interface{}, ref Ref, opts *ExpandOptions) (*PathItem, error) {
|
|
||||||
resolver, err := defaultSchemaLoader(root, nil, opts, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(PathItem)
|
|
||||||
if err := resolver.Resolve(&ref, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type schemaLoader struct {
|
|
||||||
loadingRef *Ref
|
|
||||||
startingRef *Ref
|
|
||||||
currentRef *Ref
|
|
||||||
root interface{}
|
|
||||||
options *ExpandOptions
|
|
||||||
cache ResolutionCache
|
|
||||||
loadDoc func(string) (json.RawMessage, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var idPtr, _ = jsonpointer.New("/id")
|
|
||||||
var refPtr, _ = jsonpointer.New("/$ref")
|
|
||||||
|
|
||||||
// PathLoader function to use when loading remote refs
|
|
||||||
var PathLoader func(string) (json.RawMessage, error)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
PathLoader = func(path string) (json.RawMessage, error) {
|
|
||||||
data, err := swag.LoadFromFileOrHTTP(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return json.RawMessage(data), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultSchemaLoader(
|
|
||||||
root interface{},
|
|
||||||
ref *Ref,
|
|
||||||
expandOptions *ExpandOptions,
|
|
||||||
cache ResolutionCache) (*schemaLoader, error) {
|
|
||||||
|
|
||||||
if cache == nil {
|
|
||||||
cache = resCache
|
|
||||||
}
|
|
||||||
if expandOptions == nil {
|
|
||||||
expandOptions = &ExpandOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ptr *jsonpointer.Pointer
|
|
||||||
if ref != nil {
|
|
||||||
ptr = ref.GetPointer()
|
|
||||||
}
|
|
||||||
|
|
||||||
currentRef := nextRef(root, ref, ptr)
|
|
||||||
|
|
||||||
return &schemaLoader{
|
|
||||||
loadingRef: ref,
|
|
||||||
startingRef: ref,
|
|
||||||
currentRef: currentRef,
|
|
||||||
root: root,
|
|
||||||
options: expandOptions,
|
|
||||||
cache: cache,
|
|
||||||
loadDoc: func(path string) (json.RawMessage, error) {
|
|
||||||
debugLog("fetching document at %q", path)
|
|
||||||
return PathLoader(path)
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func idFromNode(node interface{}) (*Ref, error) {
|
|
||||||
if idValue, _, err := idPtr.Get(node); err == nil {
|
|
||||||
if refStr, ok := idValue.(string); ok && refStr != "" {
|
|
||||||
idRef, err := NewRef(refStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &idRef, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextRef(startingNode interface{}, startingRef *Ref, ptr *jsonpointer.Pointer) *Ref {
|
|
||||||
if startingRef == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if ptr == nil {
|
|
||||||
return startingRef
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := startingRef
|
|
||||||
var idRef *Ref
|
|
||||||
node := startingNode
|
|
||||||
|
|
||||||
for _, tok := range ptr.DecodedTokens() {
|
|
||||||
node, _, _ = jsonpointer.GetForToken(node, tok)
|
|
||||||
if node == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
idRef, _ = idFromNode(node)
|
|
||||||
if idRef != nil {
|
|
||||||
nw, err := ret.Inherits(*idRef)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ret = nw
|
|
||||||
}
|
|
||||||
|
|
||||||
refRef, _, _ := refPtr.Get(node)
|
|
||||||
if refRef != nil {
|
|
||||||
var rf Ref
|
|
||||||
switch value := refRef.(type) {
|
|
||||||
case string:
|
|
||||||
rf, _ = NewRef(value)
|
|
||||||
}
|
|
||||||
nw, err := ret.Inherits(rf)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
nwURL := nw.GetURL()
|
|
||||||
if nwURL.Scheme == "file" || (nwURL.Scheme == "" && nwURL.Host == "") {
|
|
||||||
nwpt := filepath.ToSlash(nwURL.Path)
|
|
||||||
if filepath.IsAbs(nwpt) {
|
|
||||||
_, err := os.Stat(nwpt)
|
|
||||||
if err != nil {
|
|
||||||
nwURL.Path = filepath.Join(".", nwpt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = nw
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func debugLog(msg string, args ...interface{}) {
|
|
||||||
if Debug {
|
|
||||||
log.Printf(msg, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
|
|
||||||
refURL := ref.GetURL()
|
|
||||||
debugLog("normalizing %s against %s (%s)", ref.String(), relativeBase, refURL.String())
|
|
||||||
if strings.HasPrefix(refURL.String(), "#") {
|
|
||||||
return ref
|
|
||||||
}
|
|
||||||
|
|
||||||
if refURL.Scheme == "file" || (refURL.Scheme == "" && refURL.Host == "") {
|
|
||||||
filePath := refURL.Path
|
|
||||||
debugLog("normalizing file path: %s", filePath)
|
|
||||||
|
|
||||||
if !filepath.IsAbs(filepath.FromSlash(filePath)) && len(relativeBase) != 0 {
|
|
||||||
debugLog("joining %s with %s", relativeBase, filePath)
|
|
||||||
if fi, err := os.Stat(filepath.FromSlash(relativeBase)); err == nil {
|
|
||||||
if !fi.IsDir() {
|
|
||||||
relativeBase = filepath.Dir(filepath.FromSlash(relativeBase))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filePath = filepath.Join(filepath.FromSlash(relativeBase), filepath.FromSlash(filePath))
|
|
||||||
}
|
|
||||||
if !filepath.IsAbs(filepath.FromSlash(filePath)) {
|
|
||||||
pwd, err := os.Getwd()
|
|
||||||
if err == nil {
|
|
||||||
debugLog("joining cwd %s with %s", pwd, filePath)
|
|
||||||
filePath = filepath.Join(pwd, filepath.FromSlash(filePath))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debugLog("cleaning %s", filePath)
|
|
||||||
filePath = filepath.Clean(filepath.FromSlash(filePath))
|
|
||||||
_, err := os.Stat(filepath.FromSlash(filePath))
|
|
||||||
if err == nil {
|
|
||||||
debugLog("rewriting url %s to scheme \"\" path %s", refURL.String(), filePath)
|
|
||||||
slp := filepath.FromSlash(filePath)
|
|
||||||
if filepath.IsAbs(slp) && filepath.Separator == '\\' && len(slp) > 1 && slp[1] == ':' && ('a' <= slp[0] && slp[0] <= 'z' || 'A' <= slp[0] && slp[0] <= 'Z') {
|
|
||||||
slp = slp[2:]
|
|
||||||
}
|
|
||||||
refURL.Scheme = ""
|
|
||||||
refURL.Path = filepath.ToSlash(slp)
|
|
||||||
debugLog("new url with joined filepath: %s", refURL.String())
|
|
||||||
*ref = MustCreateRef(refURL.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debugLog("refurl: %s", ref.GetURL().String())
|
|
||||||
return ref
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *schemaLoader) resolveRef(currentRef, ref *Ref, node, target interface{}) error {
|
|
||||||
|
|
||||||
tgt := reflect.ValueOf(target)
|
|
||||||
if tgt.Kind() != reflect.Ptr {
|
|
||||||
return fmt.Errorf("resolve ref: target needs to be a pointer")
|
|
||||||
}
|
|
||||||
|
|
||||||
oldRef := currentRef
|
|
||||||
|
|
||||||
if currentRef != nil {
|
|
||||||
debugLog("resolve ref current %s new %s", currentRef.String(), ref.String())
|
|
||||||
nextRef := nextRef(node, ref, currentRef.GetPointer())
|
|
||||||
if nextRef == nil || nextRef.GetURL() == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
currentRef, err = currentRef.Inherits(*nextRef)
|
|
||||||
debugLog("resolved ref current %s", currentRef.String())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if currentRef == nil {
|
|
||||||
currentRef = ref
|
|
||||||
}
|
|
||||||
|
|
||||||
refURL := currentRef.GetURL()
|
|
||||||
if refURL == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if currentRef.IsRoot() {
|
|
||||||
nv := reflect.ValueOf(node)
|
|
||||||
reflect.Indirect(tgt).Set(reflect.Indirect(nv))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(refURL.String(), "#") {
|
|
||||||
res, _, err := ref.GetPointer().Get(node)
|
|
||||||
if err != nil {
|
|
||||||
res, _, err = ref.GetPointer().Get(r.root)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rv := reflect.Indirect(reflect.ValueOf(res))
|
|
||||||
tgtType := reflect.Indirect(tgt).Type()
|
|
||||||
if rv.Type().AssignableTo(tgtType) {
|
|
||||||
reflect.Indirect(tgt).Set(reflect.Indirect(reflect.ValueOf(res)))
|
|
||||||
} else {
|
|
||||||
if err := swag.DynamicJSONToStruct(rv.Interface(), target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
relativeBase := ""
|
|
||||||
if r.options != nil && r.options.RelativeBase != "" {
|
|
||||||
relativeBase = r.options.RelativeBase
|
|
||||||
}
|
|
||||||
normalizeFileRef(currentRef, relativeBase)
|
|
||||||
debugLog("current ref normalized file: %s", currentRef.String())
|
|
||||||
normalizeFileRef(ref, relativeBase)
|
|
||||||
debugLog("ref normalized file: %s", currentRef.String())
|
|
||||||
|
|
||||||
data, _, _, err := r.load(currentRef.GetURL())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((oldRef == nil && currentRef != nil) ||
|
|
||||||
(oldRef != nil && currentRef == nil) ||
|
|
||||||
oldRef.String() != currentRef.String()) &&
|
|
||||||
((oldRef == nil && ref != nil) ||
|
|
||||||
(oldRef != nil && ref == nil) ||
|
|
||||||
(oldRef.String() != ref.String())) {
|
|
||||||
|
|
||||||
return r.resolveRef(currentRef, ref, data, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res interface{}
|
|
||||||
if currentRef.String() != "" {
|
|
||||||
res, _, err = currentRef.GetPointer().Get(data)
|
|
||||||
if err != nil {
|
|
||||||
if strings.HasPrefix(ref.String(), "#") {
|
|
||||||
if r.loadingRef != nil {
|
|
||||||
rr, er := r.loadingRef.Inherits(*ref)
|
|
||||||
if er != nil {
|
|
||||||
return er
|
|
||||||
}
|
|
||||||
refURL = rr.GetURL()
|
|
||||||
|
|
||||||
data, _, _, err = r.load(refURL)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data = r.root
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res, _, err = ref.GetPointer().Get(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res = data
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := swag.DynamicJSONToStruct(res, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.currentRef = currentRef
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error) {
|
|
||||||
debugLog("loading schema from url: %s", refURL)
|
|
||||||
toFetch := *refURL
|
|
||||||
toFetch.Fragment = ""
|
|
||||||
|
|
||||||
data, fromCache := r.cache.Get(toFetch.String())
|
|
||||||
if !fromCache {
|
|
||||||
b, err := r.loadDoc(toFetch.String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, url.URL{}, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &data); err != nil {
|
|
||||||
return nil, url.URL{}, false, err
|
|
||||||
}
|
|
||||||
r.cache.Set(toFetch.String(), data)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, toFetch, fromCache, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *schemaLoader) Resolve(ref *Ref, target interface{}) error {
|
|
||||||
return r.resolveRef(r.currentRef, ref, r.root, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *schemaLoader) reset() {
|
|
||||||
ref := r.startingRef
|
|
||||||
|
|
||||||
var ptr *jsonpointer.Pointer
|
|
||||||
if ref != nil {
|
|
||||||
ptr = ref.GetPointer()
|
|
||||||
}
|
|
||||||
|
|
||||||
r.currentRef = nextRef(r.root, ref, ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpandSpec expands the references in a swagger spec
|
|
||||||
func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
|
|
||||||
resolver, err := defaultSchemaLoader(spec, nil, options, nil)
|
|
||||||
// Just in case this ever returns an error.
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if options == nil || !options.SkipSchemas {
|
|
||||||
for key, definition := range spec.Definitions {
|
|
||||||
var def *Schema
|
|
||||||
var err error
|
|
||||||
if def, err = expandSchema(definition, []string{"#/definitions/" + key}, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
spec.Definitions[key] = *def
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, parameter := range spec.Parameters {
|
|
||||||
if err := expandParameter(¶meter, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
spec.Parameters[key] = parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, response := range spec.Responses {
|
|
||||||
if err := expandResponse(&response, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
spec.Responses[key] = response
|
|
||||||
}
|
|
||||||
|
|
||||||
if spec.Paths != nil {
|
|
||||||
for key, path := range spec.Paths.Paths {
|
|
||||||
if err := expandPathItem(&path, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
spec.Paths.Paths[key] = path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldStopOnError(err error, opts *ExpandOptions) bool {
|
|
||||||
if err != nil && !opts.ContinueOnError {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpandSchema expands the refs in the schema object
|
|
||||||
func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error {
|
|
||||||
return ExpandSchemaWithBasePath(schema, root, cache, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpandSchemaWithBasePath expands the refs in the schema object, base path configured through expand options
|
|
||||||
func ExpandSchemaWithBasePath(schema *Schema, root interface{}, cache ResolutionCache, opts *ExpandOptions) error {
|
|
||||||
if schema == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if root == nil {
|
|
||||||
root = schema
|
|
||||||
}
|
|
||||||
|
|
||||||
nrr, _ := NewRef(schema.ID)
|
|
||||||
var rrr *Ref
|
|
||||||
if nrr.String() != "" {
|
|
||||||
switch rt := root.(type) {
|
|
||||||
case *Schema:
|
|
||||||
rid, _ := NewRef(rt.ID)
|
|
||||||
rrr, _ = rid.Inherits(nrr)
|
|
||||||
case *Swagger:
|
|
||||||
rid, _ := NewRef(rt.ID)
|
|
||||||
rrr, _ = rid.Inherits(nrr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver, err := defaultSchemaLoader(root, rrr, opts, cache)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
refs := []string{""}
|
|
||||||
if rrr != nil {
|
|
||||||
refs[0] = rrr.String()
|
|
||||||
}
|
|
||||||
var s *Schema
|
|
||||||
if s, err = expandSchema(*schema, refs, resolver); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*schema = *s
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandItems(target Schema, parentRefs []string, resolver *schemaLoader) (*Schema, error) {
|
|
||||||
if target.Items != nil {
|
|
||||||
if target.Items.Schema != nil {
|
|
||||||
t, err := expandSchema(*target.Items.Schema, parentRefs, resolver)
|
|
||||||
if err != nil {
|
|
||||||
if target.Items.Schema.ID == "" {
|
|
||||||
target.Items.Schema.ID = target.ID
|
|
||||||
if err != nil {
|
|
||||||
t, err = expandSchema(*target.Items.Schema, parentRefs, resolver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*target.Items.Schema = *t
|
|
||||||
}
|
|
||||||
for i := range target.Items.Schemas {
|
|
||||||
t, err := expandSchema(target.Items.Schemas[i], parentRefs, resolver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
target.Items.Schemas[i] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &target, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader) (*Schema, error) {
|
|
||||||
if target.Ref.String() == "" && target.Ref.IsRoot() {
|
|
||||||
debugLog("skipping expand schema for no ref and root: %v", resolver.root)
|
|
||||||
|
|
||||||
return resolver.root.(*Schema), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// t is the new expanded schema
|
|
||||||
var t *Schema
|
|
||||||
|
|
||||||
for target.Ref.String() != "" {
|
|
||||||
if swag.ContainsStringsCI(parentRefs, target.Ref.String()) {
|
|
||||||
return &target, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := resolver.Resolve(&target.Ref, &t); shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if swag.ContainsStringsCI(parentRefs, target.Ref.String()) {
|
|
||||||
debugLog("ref already exists in parent")
|
|
||||||
return &target, nil
|
|
||||||
}
|
|
||||||
parentRefs = append(parentRefs, target.Ref.String())
|
|
||||||
if t != nil {
|
|
||||||
target = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := expandItems(target, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target = *t
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range target.AllOf {
|
|
||||||
t, err := expandSchema(target.AllOf[i], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target.AllOf[i] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range target.AnyOf {
|
|
||||||
t, err := expandSchema(target.AnyOf[i], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
target.AnyOf[i] = *t
|
|
||||||
}
|
|
||||||
for i := range target.OneOf {
|
|
||||||
t, err := expandSchema(target.OneOf[i], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target.OneOf[i] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if target.Not != nil {
|
|
||||||
t, err := expandSchema(*target.Not, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
*target.Not = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range target.Properties {
|
|
||||||
t, err := expandSchema(target.Properties[k], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target.Properties[k] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if target.AdditionalProperties != nil && target.AdditionalProperties.Schema != nil {
|
|
||||||
t, err := expandSchema(*target.AdditionalProperties.Schema, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
*target.AdditionalProperties.Schema = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range target.PatternProperties {
|
|
||||||
t, err := expandSchema(target.PatternProperties[k], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target.PatternProperties[k] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range target.Dependencies {
|
|
||||||
if target.Dependencies[k].Schema != nil {
|
|
||||||
t, err := expandSchema(*target.Dependencies[k].Schema, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
*target.Dependencies[k].Schema = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if target.AdditionalItems != nil && target.AdditionalItems.Schema != nil {
|
|
||||||
t, err := expandSchema(*target.AdditionalItems.Schema, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
*target.AdditionalItems.Schema = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range target.Definitions {
|
|
||||||
t, err := expandSchema(target.Definitions[k], parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return &target, err
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
target.Definitions[k] = *t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &target, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandPathItem(pathItem *PathItem, resolver *schemaLoader) error {
|
|
||||||
if pathItem == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if pathItem.Ref.String() != "" {
|
|
||||||
if err := resolver.Resolve(&pathItem.Ref, &pathItem); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
pathItem.Ref = Ref{}
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx := range pathItem.Parameters {
|
|
||||||
if err := expandParameter(&(pathItem.Parameters[idx]), resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Get, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Head, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Options, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Put, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Post, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Patch, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := expandOperation(pathItem.Delete, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandOperation(op *Operation, resolver *schemaLoader) error {
|
|
||||||
if op == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, param := range op.Parameters {
|
|
||||||
if err := expandParameter(¶m, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
op.Parameters[i] = param
|
|
||||||
}
|
|
||||||
|
|
||||||
if op.Responses != nil {
|
|
||||||
responses := op.Responses
|
|
||||||
if err := expandResponse(responses.Default, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for code, response := range responses.StatusCodeResponses {
|
|
||||||
if err := expandResponse(&response, resolver); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
responses.StatusCodeResponses[code] = response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandResponse(response *Response, resolver *schemaLoader) error {
|
|
||||||
if response == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentRefs []string
|
|
||||||
|
|
||||||
if response.Ref.String() != "" {
|
|
||||||
parentRefs = append(parentRefs, response.Ref.String())
|
|
||||||
if err := resolver.Resolve(&response.Ref, response); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
response.Ref = Ref{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !resolver.options.SkipSchemas && response.Schema != nil {
|
|
||||||
parentRefs = append(parentRefs, response.Schema.Ref.String())
|
|
||||||
debugLog("response ref: %s", response.Schema.Ref)
|
|
||||||
if err := resolver.Resolve(&response.Schema.Ref, &response.Schema); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s, err := expandSchema(*response.Schema, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
*response.Schema = *s
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expandParameter(parameter *Parameter, resolver *schemaLoader) error {
|
|
||||||
if parameter == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentRefs []string
|
|
||||||
|
|
||||||
if parameter.Ref.String() != "" {
|
|
||||||
parentRefs = append(parentRefs, parameter.Ref.String())
|
|
||||||
if err := resolver.Resolve(¶meter.Ref, parameter); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
parameter.Ref = Ref{}
|
|
||||||
}
|
|
||||||
if !resolver.options.SkipSchemas && parameter.Schema != nil {
|
|
||||||
parentRefs = append(parentRefs, parameter.Schema.Ref.String())
|
|
||||||
if err := resolver.Resolve(¶meter.Schema.Ref, ¶meter.Schema); shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s, err := expandSchema(*parameter.Schema, parentRefs, resolver)
|
|
||||||
if shouldStopOnError(err, resolver.options) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolver.reset()
|
|
||||||
*parameter.Schema = *s
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
+35
-11
@@ -35,22 +35,39 @@
|
|||||||
package proto
|
package proto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Clone returns a deep copy of a protocol buffer.
|
// Clone returns a deep copy of a protocol buffer.
|
||||||
func Clone(pb Message) Message {
|
func Clone(src Message) Message {
|
||||||
in := reflect.ValueOf(pb)
|
in := reflect.ValueOf(src)
|
||||||
if in.IsNil() {
|
if in.IsNil() {
|
||||||
return pb
|
return src
|
||||||
}
|
}
|
||||||
|
|
||||||
out := reflect.New(in.Type().Elem())
|
out := reflect.New(in.Type().Elem())
|
||||||
// out is empty so a merge is a deep copy.
|
dst := out.Interface().(Message)
|
||||||
mergeStruct(out.Elem(), in.Elem())
|
Merge(dst, src)
|
||||||
return out.Interface().(Message)
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merger is the interface representing objects that can merge messages of the same type.
|
||||||
|
type Merger interface {
|
||||||
|
// Merge merges src into this message.
|
||||||
|
// Required and optional fields that are set in src will be set to that value in dst.
|
||||||
|
// Elements of repeated fields will be appended.
|
||||||
|
//
|
||||||
|
// Merge may panic if called with a different argument type than the receiver.
|
||||||
|
Merge(src Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generatedMerger is the custom merge method that generated protos will have.
|
||||||
|
// We must add this method since a generate Merge method will conflict with
|
||||||
|
// many existing protos that have a Merge data field already defined.
|
||||||
|
type generatedMerger interface {
|
||||||
|
XXX_Merge(src Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge merges src into dst.
|
// Merge merges src into dst.
|
||||||
@@ -58,17 +75,24 @@ func Clone(pb Message) Message {
|
|||||||
// Elements of repeated fields will be appended.
|
// Elements of repeated fields will be appended.
|
||||||
// Merge panics if src and dst are not the same type, or if dst is nil.
|
// Merge panics if src and dst are not the same type, or if dst is nil.
|
||||||
func Merge(dst, src Message) {
|
func Merge(dst, src Message) {
|
||||||
|
if m, ok := dst.(Merger); ok {
|
||||||
|
m.Merge(src)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
in := reflect.ValueOf(src)
|
in := reflect.ValueOf(src)
|
||||||
out := reflect.ValueOf(dst)
|
out := reflect.ValueOf(dst)
|
||||||
if out.IsNil() {
|
if out.IsNil() {
|
||||||
panic("proto: nil destination")
|
panic("proto: nil destination")
|
||||||
}
|
}
|
||||||
if in.Type() != out.Type() {
|
if in.Type() != out.Type() {
|
||||||
// Explicit test prior to mergeStruct so that mistyped nils will fail
|
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
|
||||||
panic("proto: type mismatch")
|
|
||||||
}
|
}
|
||||||
if in.IsNil() {
|
if in.IsNil() {
|
||||||
// Merging nil into non-nil is a quiet no-op
|
return // Merge from nil src is a noop
|
||||||
|
}
|
||||||
|
if m, ok := dst.(generatedMerger); ok {
|
||||||
|
m.XXX_Merge(src)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mergeStruct(out.Elem(), in.Elem())
|
mergeStruct(out.Elem(), in.Elem())
|
||||||
@@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) {
|
|||||||
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
|
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
if emIn, ok := extendable(in.Addr().Interface()); ok {
|
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
||||||
emOut, _ := extendable(out.Addr().Interface())
|
emOut, _ := extendable(out.Addr().Interface())
|
||||||
mIn, muIn := emIn.extensionsRead()
|
mIn, muIn := emIn.extensionsRead()
|
||||||
if mIn != nil {
|
if mIn != nil {
|
||||||
|
|||||||
+63
-605
@@ -39,8 +39,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// errOverflow is returned when an integer is too large to be represented.
|
// errOverflow is returned when an integer is too large to be represented.
|
||||||
@@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow")
|
|||||||
// wire type is encountered. It does not get returned to user code.
|
// wire type is encountered. It does not get returned to user code.
|
||||||
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
||||||
|
|
||||||
// The fundamental decoders that interpret bytes on the wire.
|
|
||||||
// Those that take integer types all return uint64 and are
|
|
||||||
// therefore of type valueDecoder.
|
|
||||||
|
|
||||||
// DecodeVarint reads a varint-encoded integer from the slice.
|
// DecodeVarint reads a varint-encoded integer from the slice.
|
||||||
// It returns the integer and the number of bytes consumed, or
|
// It returns the integer and the number of bytes consumed, or
|
||||||
// zero if there is not enough.
|
// zero if there is not enough.
|
||||||
@@ -267,9 +261,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are not ValueDecoders: they produce an array of bytes or a string.
|
|
||||||
// bytes, embedded messages
|
|
||||||
|
|
||||||
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
|
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
|
||||||
// This is the format used for the bytes protocol buffer
|
// This is the format used for the bytes protocol buffer
|
||||||
// type and for embedded messages.
|
// type and for embedded messages.
|
||||||
@@ -311,81 +302,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
|
|||||||
return string(buf), nil
|
return string(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
|
|
||||||
// If the protocol buffer has extensions, and the field matches, add it as an extension.
|
|
||||||
// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
|
|
||||||
func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
|
|
||||||
oi := o.index
|
|
||||||
|
|
||||||
err := o.skip(t, tag, wire)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !unrecField.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr := structPointer_Bytes(base, unrecField)
|
|
||||||
|
|
||||||
// Add the skipped field to struct field
|
|
||||||
obuf := o.buf
|
|
||||||
|
|
||||||
o.buf = *ptr
|
|
||||||
o.EncodeVarint(uint64(tag<<3 | wire))
|
|
||||||
*ptr = append(o.buf, obuf[oi:o.index]...)
|
|
||||||
|
|
||||||
o.buf = obuf
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
|
|
||||||
func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
|
|
||||||
|
|
||||||
var u uint64
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch wire {
|
|
||||||
case WireVarint:
|
|
||||||
_, err = o.DecodeVarint()
|
|
||||||
case WireFixed64:
|
|
||||||
_, err = o.DecodeFixed64()
|
|
||||||
case WireBytes:
|
|
||||||
_, err = o.DecodeRawBytes(false)
|
|
||||||
case WireFixed32:
|
|
||||||
_, err = o.DecodeFixed32()
|
|
||||||
case WireStartGroup:
|
|
||||||
for {
|
|
||||||
u, err = o.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fwire := int(u & 0x7)
|
|
||||||
if fwire == WireEndGroup {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ftag := int(u >> 3)
|
|
||||||
err = o.skip(t, ftag, fwire)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshaler is the interface representing objects that can
|
// Unmarshaler is the interface representing objects that can
|
||||||
// unmarshal themselves. The method should reset the receiver before
|
// unmarshal themselves. The argument points to data that may be
|
||||||
// decoding starts. The argument points to data that may be
|
|
||||||
// overwritten, so implementations should not keep references to the
|
// overwritten, so implementations should not keep references to the
|
||||||
// buffer.
|
// buffer.
|
||||||
|
// Unmarshal implementations should not clear the receiver.
|
||||||
|
// Any unmarshaled data should be merged into the receiver.
|
||||||
|
// Callers of Unmarshal that do not want to retain existing data
|
||||||
|
// should Reset the receiver before calling Unmarshal.
|
||||||
type Unmarshaler interface {
|
type Unmarshaler interface {
|
||||||
Unmarshal([]byte) error
|
Unmarshal([]byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newUnmarshaler is the interface representing objects that can
|
||||||
|
// unmarshal themselves. The semantics are identical to Unmarshaler.
|
||||||
|
//
|
||||||
|
// This exists to support protoc-gen-go generated messages.
|
||||||
|
// The proto package will stop type-asserting to this interface in the future.
|
||||||
|
//
|
||||||
|
// DO NOT DEPEND ON THIS.
|
||||||
|
type newUnmarshaler interface {
|
||||||
|
XXX_Unmarshal([]byte) error
|
||||||
|
}
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in buf and places the
|
// Unmarshal parses the protocol buffer representation in buf and places the
|
||||||
// decoded result in pb. If the struct underlying pb does not match
|
// decoded result in pb. If the struct underlying pb does not match
|
||||||
// the data in buf, the results can be unpredictable.
|
// the data in buf, the results can be unpredictable.
|
||||||
@@ -395,7 +334,13 @@ type Unmarshaler interface {
|
|||||||
// to preserve and append to existing data.
|
// to preserve and append to existing data.
|
||||||
func Unmarshal(buf []byte, pb Message) error {
|
func Unmarshal(buf []byte, pb Message) error {
|
||||||
pb.Reset()
|
pb.Reset()
|
||||||
return UnmarshalMerge(buf, pb)
|
if u, ok := pb.(newUnmarshaler); ok {
|
||||||
|
return u.XXX_Unmarshal(buf)
|
||||||
|
}
|
||||||
|
if u, ok := pb.(Unmarshaler); ok {
|
||||||
|
return u.Unmarshal(buf)
|
||||||
|
}
|
||||||
|
return NewBuffer(buf).Unmarshal(pb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalMerge parses the protocol buffer representation in buf and
|
// UnmarshalMerge parses the protocol buffer representation in buf and
|
||||||
@@ -405,8 +350,16 @@ func Unmarshal(buf []byte, pb Message) error {
|
|||||||
// UnmarshalMerge merges into existing data in pb.
|
// UnmarshalMerge merges into existing data in pb.
|
||||||
// Most code should use Unmarshal instead.
|
// Most code should use Unmarshal instead.
|
||||||
func UnmarshalMerge(buf []byte, pb Message) error {
|
func UnmarshalMerge(buf []byte, pb Message) error {
|
||||||
// If the object can unmarshal itself, let it.
|
if u, ok := pb.(newUnmarshaler); ok {
|
||||||
|
return u.XXX_Unmarshal(buf)
|
||||||
|
}
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
if u, ok := pb.(Unmarshaler); ok {
|
||||||
|
// NOTE: The history of proto have unfortunately been inconsistent
|
||||||
|
// whether Unmarshaler should or should not implicitly clear itself.
|
||||||
|
// Some implementations do, most do not.
|
||||||
|
// Thus, calling this here may or may not do what people want.
|
||||||
|
//
|
||||||
|
// See https://github.com/golang/protobuf/issues/424
|
||||||
return u.Unmarshal(buf)
|
return u.Unmarshal(buf)
|
||||||
}
|
}
|
||||||
return NewBuffer(buf).Unmarshal(pb)
|
return NewBuffer(buf).Unmarshal(pb)
|
||||||
@@ -422,12 +375,17 @@ func (p *Buffer) DecodeMessage(pb Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecodeGroup reads a tag-delimited group from the Buffer.
|
// DecodeGroup reads a tag-delimited group from the Buffer.
|
||||||
|
// StartGroup tag is already consumed. This function consumes
|
||||||
|
// EndGroup tag.
|
||||||
func (p *Buffer) DecodeGroup(pb Message) error {
|
func (p *Buffer) DecodeGroup(pb Message) error {
|
||||||
typ, base, err := getbase(pb)
|
b := p.buf[p.index:]
|
||||||
if err != nil {
|
x, y := findEndGroup(b)
|
||||||
return err
|
if x < 0 {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
|
err := Unmarshal(b[:x], pb)
|
||||||
|
p.index += y
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in the
|
// Unmarshal parses the protocol buffer representation in the
|
||||||
@@ -438,533 +396,33 @@ func (p *Buffer) DecodeGroup(pb Message) error {
|
|||||||
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
|
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
|
||||||
func (p *Buffer) Unmarshal(pb Message) error {
|
func (p *Buffer) Unmarshal(pb Message) error {
|
||||||
// If the object can unmarshal itself, let it.
|
// If the object can unmarshal itself, let it.
|
||||||
|
if u, ok := pb.(newUnmarshaler); ok {
|
||||||
|
err := u.XXX_Unmarshal(p.buf[p.index:])
|
||||||
|
p.index = len(p.buf)
|
||||||
|
return err
|
||||||
|
}
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
if u, ok := pb.(Unmarshaler); ok {
|
||||||
|
// NOTE: The history of proto have unfortunately been inconsistent
|
||||||
|
// whether Unmarshaler should or should not implicitly clear itself.
|
||||||
|
// Some implementations do, most do not.
|
||||||
|
// Thus, calling this here may or may not do what people want.
|
||||||
|
//
|
||||||
|
// See https://github.com/golang/protobuf/issues/424
|
||||||
err := u.Unmarshal(p.buf[p.index:])
|
err := u.Unmarshal(p.buf[p.index:])
|
||||||
p.index = len(p.buf)
|
p.index = len(p.buf)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
typ, base, err := getbase(pb)
|
// Slow workaround for messages that aren't Unmarshalers.
|
||||||
if err != nil {
|
// This includes some hand-coded .pb.go files and
|
||||||
return err
|
// bootstrap protos.
|
||||||
}
|
// TODO: fix all of those and then add Unmarshal to
|
||||||
|
// the Message interface. Then:
|
||||||
err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
|
// The cast above and code below can be deleted.
|
||||||
|
// The old unmarshaler can be deleted.
|
||||||
if collectStats {
|
// Clients can call Unmarshal directly (can already do that, actually).
|
||||||
stats.Decode++
|
var info InternalMessageInfo
|
||||||
}
|
err := info.Unmarshal(pb, p.buf[p.index:])
|
||||||
|
p.index = len(p.buf)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmarshalType does the work of unmarshaling a structure.
|
|
||||||
func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
|
|
||||||
var state errorState
|
|
||||||
required, reqFields := prop.reqCount, uint64(0)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
for err == nil && o.index < len(o.buf) {
|
|
||||||
oi := o.index
|
|
||||||
var u uint64
|
|
||||||
u, err = o.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
wire := int(u & 0x7)
|
|
||||||
if wire == WireEndGroup {
|
|
||||||
if is_group {
|
|
||||||
if required > 0 {
|
|
||||||
// Not enough information to determine the exact field.
|
|
||||||
// (See below.)
|
|
||||||
return &RequiredNotSetError{"{Unknown}"}
|
|
||||||
}
|
|
||||||
return nil // input is satisfied
|
|
||||||
}
|
|
||||||
return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
|
|
||||||
}
|
|
||||||
tag := int(u >> 3)
|
|
||||||
if tag <= 0 {
|
|
||||||
return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
|
|
||||||
}
|
|
||||||
fieldnum, ok := prop.decoderTags.get(tag)
|
|
||||||
if !ok {
|
|
||||||
// Maybe it's an extension?
|
|
||||||
if prop.extendable {
|
|
||||||
if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
|
|
||||||
if err = o.skip(st, tag, wire); err == nil {
|
|
||||||
extmap := e.extensionsWrite()
|
|
||||||
ext := extmap[int32(tag)] // may be missing
|
|
||||||
ext.enc = append(ext.enc, o.buf[oi:o.index]...)
|
|
||||||
extmap[int32(tag)] = ext
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Maybe it's a oneof?
|
|
||||||
if prop.oneofUnmarshaler != nil {
|
|
||||||
m := structPointer_Interface(base, st).(Message)
|
|
||||||
// First return value indicates whether tag is a oneof field.
|
|
||||||
ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
|
|
||||||
if err == ErrInternalBadWireType {
|
|
||||||
// Map the error to something more descriptive.
|
|
||||||
// Do the formatting here to save generated code space.
|
|
||||||
err = fmt.Errorf("bad wiretype for oneof field in %T", m)
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p := prop.Prop[fieldnum]
|
|
||||||
|
|
||||||
if p.dec == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dec := p.dec
|
|
||||||
if wire != WireStartGroup && wire != p.WireType {
|
|
||||||
if wire == WireBytes && p.packedDec != nil {
|
|
||||||
// a packable field
|
|
||||||
dec = p.packedDec
|
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
decErr := dec(o, p, base)
|
|
||||||
if decErr != nil && !state.shouldContinue(decErr, p) {
|
|
||||||
err = decErr
|
|
||||||
}
|
|
||||||
if err == nil && p.Required {
|
|
||||||
// Successfully decoded a required field.
|
|
||||||
if tag <= 64 {
|
|
||||||
// use bitmap for fields 1-64 to catch field reuse.
|
|
||||||
var mask uint64 = 1 << uint64(tag-1)
|
|
||||||
if reqFields&mask == 0 {
|
|
||||||
// new required field
|
|
||||||
reqFields |= mask
|
|
||||||
required--
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is imprecise. It can be fooled by a required field
|
|
||||||
// with a tag > 64 that is encoded twice; that's very rare.
|
|
||||||
// A fully correct implementation would require allocating
|
|
||||||
// a data structure, which we would like to avoid.
|
|
||||||
required--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
if is_group {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
if state.err != nil {
|
|
||||||
return state.err
|
|
||||||
}
|
|
||||||
if required > 0 {
|
|
||||||
// Not enough information to determine the exact field. If we use extra
|
|
||||||
// CPU, we could determine the field only if the missing required field
|
|
||||||
// has a tag <= 64 and we check reqFields.
|
|
||||||
return &RequiredNotSetError{"{Unknown}"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Individual type decoders
|
|
||||||
// For each,
|
|
||||||
// u is the decoded value,
|
|
||||||
// v is a pointer to the field (pointer) in the struct
|
|
||||||
|
|
||||||
// Sizes of the pools to allocate inside the Buffer.
|
|
||||||
// The goal is modest amortization and allocation
|
|
||||||
// on at least 16-byte boundaries.
|
|
||||||
const (
|
|
||||||
boolPoolSize = 16
|
|
||||||
uint32PoolSize = 8
|
|
||||||
uint64PoolSize = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Decode a bool.
|
|
||||||
func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(o.bools) == 0 {
|
|
||||||
o.bools = make([]bool, boolPoolSize)
|
|
||||||
}
|
|
||||||
o.bools[0] = u != 0
|
|
||||||
*structPointer_Bool(base, p.field) = &o.bools[0]
|
|
||||||
o.bools = o.bools[1:]
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*structPointer_BoolVal(base, p.field) = u != 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode an int32.
|
|
||||||
func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode an int64.
|
|
||||||
func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
word64_Set(structPointer_Word64(base, p.field), o, u)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a string.
|
|
||||||
func (o *Buffer) dec_string(p *Properties, base structPointer) error {
|
|
||||||
s, err := o.DecodeStringBytes()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*structPointer_String(base, p.field) = &s
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
|
|
||||||
s, err := o.DecodeStringBytes()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*structPointer_StringVal(base, p.field) = s
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of bytes ([]byte).
|
|
||||||
func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
|
|
||||||
b, err := o.DecodeRawBytes(true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*structPointer_Bytes(base, p.field) = b
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of bools ([]bool).
|
|
||||||
func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v := structPointer_BoolSlice(base, p.field)
|
|
||||||
*v = append(*v, u != 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of bools ([]bool) in packed format.
|
|
||||||
func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
|
|
||||||
v := structPointer_BoolSlice(base, p.field)
|
|
||||||
|
|
||||||
nn, err := o.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nb := int(nn) // number of bytes of encoded bools
|
|
||||||
fin := o.index + nb
|
|
||||||
if fin < o.index {
|
|
||||||
return errOverflow
|
|
||||||
}
|
|
||||||
|
|
||||||
y := *v
|
|
||||||
for o.index < fin {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
y = append(y, u != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
*v = y
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of int32s ([]int32).
|
|
||||||
func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
structPointer_Word32Slice(base, p.field).Append(uint32(u))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of int32s ([]int32) in packed format.
|
|
||||||
func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
|
|
||||||
v := structPointer_Word32Slice(base, p.field)
|
|
||||||
|
|
||||||
nn, err := o.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nb := int(nn) // number of bytes of encoded int32s
|
|
||||||
|
|
||||||
fin := o.index + nb
|
|
||||||
if fin < o.index {
|
|
||||||
return errOverflow
|
|
||||||
}
|
|
||||||
for o.index < fin {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Append(uint32(u))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of int64s ([]int64).
|
|
||||||
func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
structPointer_Word64Slice(base, p.field).Append(u)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of int64s ([]int64) in packed format.
|
|
||||||
func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
|
|
||||||
v := structPointer_Word64Slice(base, p.field)
|
|
||||||
|
|
||||||
nn, err := o.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nb := int(nn) // number of bytes of encoded int64s
|
|
||||||
|
|
||||||
fin := o.index + nb
|
|
||||||
if fin < o.index {
|
|
||||||
return errOverflow
|
|
||||||
}
|
|
||||||
for o.index < fin {
|
|
||||||
u, err := p.valDec(o)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Append(u)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of strings ([]string).
|
|
||||||
func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
|
|
||||||
s, err := o.DecodeStringBytes()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v := structPointer_StringSlice(base, p.field)
|
|
||||||
*v = append(*v, s)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of slice of bytes ([][]byte).
|
|
||||||
func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
|
|
||||||
b, err := o.DecodeRawBytes(true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v := structPointer_BytesSlice(base, p.field)
|
|
||||||
*v = append(*v, b)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a map field.
|
|
||||||
func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
|
|
||||||
raw, err := o.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
oi := o.index // index at the end of this map entry
|
|
||||||
o.index -= len(raw) // move buffer back to start of map entry
|
|
||||||
|
|
||||||
mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
|
|
||||||
if mptr.Elem().IsNil() {
|
|
||||||
mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
|
|
||||||
}
|
|
||||||
v := mptr.Elem() // map[K]V
|
|
||||||
|
|
||||||
// Prepare addressable doubly-indirect placeholders for the key and value types.
|
|
||||||
// See enc_new_map for why.
|
|
||||||
keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
|
|
||||||
keybase := toStructPointer(keyptr.Addr()) // **K
|
|
||||||
|
|
||||||
var valbase structPointer
|
|
||||||
var valptr reflect.Value
|
|
||||||
switch p.mtype.Elem().Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
// []byte
|
|
||||||
var dummy []byte
|
|
||||||
valptr = reflect.ValueOf(&dummy) // *[]byte
|
|
||||||
valbase = toStructPointer(valptr) // *[]byte
|
|
||||||
case reflect.Ptr:
|
|
||||||
// message; valptr is **Msg; need to allocate the intermediate pointer
|
|
||||||
valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
|
|
||||||
valptr.Set(reflect.New(valptr.Type().Elem()))
|
|
||||||
valbase = toStructPointer(valptr)
|
|
||||||
default:
|
|
||||||
// everything else
|
|
||||||
valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
|
|
||||||
valbase = toStructPointer(valptr.Addr()) // **V
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode.
|
|
||||||
// This parses a restricted wire format, namely the encoding of a message
|
|
||||||
// with two fields. See enc_new_map for the format.
|
|
||||||
for o.index < oi {
|
|
||||||
// tagcode for key and value properties are always a single byte
|
|
||||||
// because they have tags 1 and 2.
|
|
||||||
tagcode := o.buf[o.index]
|
|
||||||
o.index++
|
|
||||||
switch tagcode {
|
|
||||||
case p.mkeyprop.tagcode[0]:
|
|
||||||
if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case p.mvalprop.tagcode[0]:
|
|
||||||
if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// TODO: Should we silently skip this instead?
|
|
||||||
return fmt.Errorf("proto: bad map data tag %d", raw[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keyelem, valelem := keyptr.Elem(), valptr.Elem()
|
|
||||||
if !keyelem.IsValid() {
|
|
||||||
keyelem = reflect.Zero(p.mtype.Key())
|
|
||||||
}
|
|
||||||
if !valelem.IsValid() {
|
|
||||||
valelem = reflect.Zero(p.mtype.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
v.SetMapIndex(keyelem, valelem)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a group.
|
|
||||||
func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
|
|
||||||
bas := structPointer_GetStructPointer(base, p.field)
|
|
||||||
if structPointer_IsNil(bas) {
|
|
||||||
// allocate new nested message
|
|
||||||
bas = toStructPointer(reflect.New(p.stype))
|
|
||||||
structPointer_SetStructPointer(base, p.field, bas)
|
|
||||||
}
|
|
||||||
return o.unmarshalType(p.stype, p.sprop, true, bas)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode an embedded message.
|
|
||||||
func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
|
|
||||||
raw, e := o.DecodeRawBytes(false)
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
bas := structPointer_GetStructPointer(base, p.field)
|
|
||||||
if structPointer_IsNil(bas) {
|
|
||||||
// allocate new nested message
|
|
||||||
bas = toStructPointer(reflect.New(p.stype))
|
|
||||||
structPointer_SetStructPointer(base, p.field, bas)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the object can unmarshal itself, let it.
|
|
||||||
if p.isUnmarshaler {
|
|
||||||
iv := structPointer_Interface(bas, p.stype)
|
|
||||||
return iv.(Unmarshaler).Unmarshal(raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
obuf := o.buf
|
|
||||||
oi := o.index
|
|
||||||
o.buf = raw
|
|
||||||
o.index = 0
|
|
||||||
|
|
||||||
err = o.unmarshalType(p.stype, p.sprop, false, bas)
|
|
||||||
o.buf = obuf
|
|
||||||
o.index = oi
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of embedded messages.
|
|
||||||
func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
|
|
||||||
return o.dec_slice_struct(p, false, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of embedded groups.
|
|
||||||
func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
|
|
||||||
return o.dec_slice_struct(p, true, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a slice of structs ([]*struct).
|
|
||||||
func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
|
|
||||||
v := reflect.New(p.stype)
|
|
||||||
bas := toStructPointer(v)
|
|
||||||
structPointer_StructPointerSlice(base, p.field).Append(bas)
|
|
||||||
|
|
||||||
if is_group {
|
|
||||||
err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
raw, err := o.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the object can unmarshal itself, let it.
|
|
||||||
if p.isUnmarshaler {
|
|
||||||
iv := v.Interface()
|
|
||||||
return iv.(Unmarshaler).Unmarshal(raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
obuf := o.buf
|
|
||||||
oi := o.index
|
|
||||||
o.buf = raw
|
|
||||||
o.index = 0
|
|
||||||
|
|
||||||
err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
|
|
||||||
|
|
||||||
o.buf = obuf
|
|
||||||
o.index = oi
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+350
@@ -0,0 +1,350 @@
|
|||||||
|
// Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
//
|
||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// https://github.com/golang/protobuf
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type generatedDiscarder interface {
|
||||||
|
XXX_DiscardUnknown()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscardUnknown recursively discards all unknown fields from this message
|
||||||
|
// and all embedded messages.
|
||||||
|
//
|
||||||
|
// When unmarshaling a message with unrecognized fields, the tags and values
|
||||||
|
// of such fields are preserved in the Message. This allows a later call to
|
||||||
|
// marshal to be able to produce a message that continues to have those
|
||||||
|
// unrecognized fields. To avoid this, DiscardUnknown is used to
|
||||||
|
// explicitly clear the unknown fields after unmarshaling.
|
||||||
|
//
|
||||||
|
// For proto2 messages, the unknown fields of message extensions are only
|
||||||
|
// discarded from messages that have been accessed via GetExtension.
|
||||||
|
func DiscardUnknown(m Message) {
|
||||||
|
if m, ok := m.(generatedDiscarder); ok {
|
||||||
|
m.XXX_DiscardUnknown()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
|
||||||
|
// but the master branch has no implementation for InternalMessageInfo,
|
||||||
|
// so it would be more work to replicate that approach.
|
||||||
|
discardLegacy(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscardUnknown recursively discards all unknown fields.
|
||||||
|
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
|
||||||
|
di := atomicLoadDiscardInfo(&a.discard)
|
||||||
|
if di == nil {
|
||||||
|
di = getDiscardInfo(reflect.TypeOf(m).Elem())
|
||||||
|
atomicStoreDiscardInfo(&a.discard, di)
|
||||||
|
}
|
||||||
|
di.discard(toPointer(&m))
|
||||||
|
}
|
||||||
|
|
||||||
|
type discardInfo struct {
|
||||||
|
typ reflect.Type
|
||||||
|
|
||||||
|
initialized int32 // 0: only typ is valid, 1: everything is valid
|
||||||
|
lock sync.Mutex
|
||||||
|
|
||||||
|
fields []discardFieldInfo
|
||||||
|
unrecognized field
|
||||||
|
}
|
||||||
|
|
||||||
|
type discardFieldInfo struct {
|
||||||
|
field field // Offset of field, guaranteed to be valid
|
||||||
|
discard func(src pointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
discardInfoMap = map[reflect.Type]*discardInfo{}
|
||||||
|
discardInfoLock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDiscardInfo(t reflect.Type) *discardInfo {
|
||||||
|
discardInfoLock.Lock()
|
||||||
|
defer discardInfoLock.Unlock()
|
||||||
|
di := discardInfoMap[t]
|
||||||
|
if di == nil {
|
||||||
|
di = &discardInfo{typ: t}
|
||||||
|
discardInfoMap[t] = di
|
||||||
|
}
|
||||||
|
return di
|
||||||
|
}
|
||||||
|
|
||||||
|
func (di *discardInfo) discard(src pointer) {
|
||||||
|
if src.isNil() {
|
||||||
|
return // Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
if atomic.LoadInt32(&di.initialized) == 0 {
|
||||||
|
di.computeDiscardInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fi := range di.fields {
|
||||||
|
sfp := src.offset(fi.field)
|
||||||
|
fi.discard(sfp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For proto2 messages, only discard unknown fields in message extensions
|
||||||
|
// that have been accessed via GetExtension.
|
||||||
|
if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
|
||||||
|
// Ignore lock since DiscardUnknown is not concurrency safe.
|
||||||
|
emm, _ := em.extensionsRead()
|
||||||
|
for _, mx := range emm {
|
||||||
|
if m, ok := mx.value.(Message); ok {
|
||||||
|
DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if di.unrecognized.IsValid() {
|
||||||
|
*src.offset(di.unrecognized).toBytes() = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (di *discardInfo) computeDiscardInfo() {
|
||||||
|
di.lock.Lock()
|
||||||
|
defer di.lock.Unlock()
|
||||||
|
if di.initialized != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t := di.typ
|
||||||
|
n := t.NumField()
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if strings.HasPrefix(f.Name, "XXX_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dfi := discardFieldInfo{field: toField(&f)}
|
||||||
|
tf := f.Type
|
||||||
|
|
||||||
|
// Unwrap tf to get its most basic type.
|
||||||
|
var isPointer, isSlice bool
|
||||||
|
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
||||||
|
isSlice = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if tf.Kind() == reflect.Ptr {
|
||||||
|
isPointer = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
||||||
|
panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tf.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
switch {
|
||||||
|
case !isPointer:
|
||||||
|
panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
|
||||||
|
case isSlice: // E.g., []*pb.T
|
||||||
|
di := getDiscardInfo(tf)
|
||||||
|
dfi.discard = func(src pointer) {
|
||||||
|
sps := src.getPointerSlice()
|
||||||
|
for _, sp := range sps {
|
||||||
|
if !sp.isNil() {
|
||||||
|
di.discard(sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., *pb.T
|
||||||
|
di := getDiscardInfo(tf)
|
||||||
|
dfi.discard = func(src pointer) {
|
||||||
|
sp := src.getPointer()
|
||||||
|
if !sp.isNil() {
|
||||||
|
di.discard(sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
|
||||||
|
default: // E.g., map[K]V
|
||||||
|
if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
|
||||||
|
dfi.discard = func(src pointer) {
|
||||||
|
sm := src.asPointerTo(tf).Elem()
|
||||||
|
if sm.Len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, key := range sm.MapKeys() {
|
||||||
|
val := sm.MapIndex(key)
|
||||||
|
DiscardUnknown(val.Interface().(Message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dfi.discard = func(pointer) {} // Noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
// Must be oneof field.
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
|
||||||
|
default: // E.g., interface{}
|
||||||
|
// TODO: Make this faster?
|
||||||
|
dfi.discard = func(src pointer) {
|
||||||
|
su := src.asPointerTo(tf).Elem()
|
||||||
|
if !su.IsNil() {
|
||||||
|
sv := su.Elem().Elem().Field(0)
|
||||||
|
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch sv.Type().Kind() {
|
||||||
|
case reflect.Ptr: // Proto struct (e.g., *T)
|
||||||
|
DiscardUnknown(sv.Interface().(Message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
di.fields = append(di.fields, dfi)
|
||||||
|
}
|
||||||
|
|
||||||
|
di.unrecognized = invalidField
|
||||||
|
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
|
||||||
|
if f.Type != reflect.TypeOf([]byte{}) {
|
||||||
|
panic("expected XXX_unrecognized to be of type []byte")
|
||||||
|
}
|
||||||
|
di.unrecognized = toField(&f)
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StoreInt32(&di.initialized, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func discardLegacy(m Message) {
|
||||||
|
v := reflect.ValueOf(m)
|
||||||
|
if v.Kind() != reflect.Ptr || v.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
if v.Kind() != reflect.Struct {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if strings.HasPrefix(f.Name, "XXX_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vf := v.Field(i)
|
||||||
|
tf := f.Type
|
||||||
|
|
||||||
|
// Unwrap tf to get its most basic type.
|
||||||
|
var isPointer, isSlice bool
|
||||||
|
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
||||||
|
isSlice = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if tf.Kind() == reflect.Ptr {
|
||||||
|
isPointer = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
||||||
|
panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tf.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
switch {
|
||||||
|
case !isPointer:
|
||||||
|
panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
|
||||||
|
case isSlice: // E.g., []*pb.T
|
||||||
|
for j := 0; j < vf.Len(); j++ {
|
||||||
|
discardLegacy(vf.Index(j).Interface().(Message))
|
||||||
|
}
|
||||||
|
default: // E.g., *pb.T
|
||||||
|
discardLegacy(vf.Interface().(Message))
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
|
||||||
|
default: // E.g., map[K]V
|
||||||
|
tv := vf.Type().Elem()
|
||||||
|
if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
|
||||||
|
for _, key := range vf.MapKeys() {
|
||||||
|
val := vf.MapIndex(key)
|
||||||
|
discardLegacy(val.Interface().(Message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
// Must be oneof field.
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
|
||||||
|
default: // E.g., test_proto.isCommunique_Union interface
|
||||||
|
if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
|
||||||
|
vf = vf.Elem() // E.g., *test_proto.Communique_Msg
|
||||||
|
if !vf.IsNil() {
|
||||||
|
vf = vf.Elem() // E.g., test_proto.Communique_Msg
|
||||||
|
vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
|
||||||
|
if vf.Kind() == reflect.Ptr {
|
||||||
|
discardLegacy(vf.Interface().(Message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
|
||||||
|
if vf.Type() != reflect.TypeOf([]byte{}) {
|
||||||
|
panic("expected XXX_unrecognized to be of type []byte")
|
||||||
|
}
|
||||||
|
vf.Set(reflect.ValueOf([]byte(nil)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// For proto2 messages, only discard unknown fields in message extensions
|
||||||
|
// that have been accessed via GetExtension.
|
||||||
|
if em, err := extendable(m); err == nil {
|
||||||
|
// Ignore lock since discardLegacy is not concurrency safe.
|
||||||
|
emm, _ := em.extensionsRead()
|
||||||
|
for _, mx := range emm {
|
||||||
|
if m, ok := mx.value.(Message); ok {
|
||||||
|
discardLegacy(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-1165
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool {
|
|||||||
// set/unset mismatch
|
// set/unset mismatch
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
b1, ok := f1.Interface().(raw)
|
|
||||||
if ok {
|
|
||||||
b2 := f2.Interface().(raw)
|
|
||||||
// RawMessage
|
|
||||||
if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f1, f2 = f1.Elem(), f2.Elem()
|
f1, f2 = f1.Elem(), f2.Elem()
|
||||||
}
|
}
|
||||||
if !equalAny(f1, f2, sprop.Prop[i]) {
|
if !equalAny(f1, f2, sprop.Prop[i]) {
|
||||||
@@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
|
|||||||
|
|
||||||
u1 := uf.Bytes()
|
u1 := uf.Bytes()
|
||||||
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
|
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
|
||||||
if !bytes.Equal(u1, u2) {
|
return bytes.Equal(u1, u2)
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1 and v2 are known to have the same type.
|
// v1 and v2 are known to have the same type.
|
||||||
@@ -261,6 +248,15 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|||||||
|
|
||||||
m1, m2 := e1.value, e2.value
|
m1, m2 := e1.value, e2.value
|
||||||
|
|
||||||
|
if m1 == nil && m2 == nil {
|
||||||
|
// Both have only encoded form.
|
||||||
|
if bytes.Equal(e1.enc, e2.enc) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The bytes are different, but the extensions might still be
|
||||||
|
// equal. We need to decode them to compare.
|
||||||
|
}
|
||||||
|
|
||||||
if m1 != nil && m2 != nil {
|
if m1 != nil && m2 != nil {
|
||||||
// Both are unencoded.
|
// Both are unencoded.
|
||||||
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
||||||
@@ -276,8 +272,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|||||||
desc = m[extNum]
|
desc = m[extNum]
|
||||||
}
|
}
|
||||||
if desc == nil {
|
if desc == nil {
|
||||||
|
// If both have only encoded form and the bytes are the same,
|
||||||
|
// it is handled above. We get here when the bytes are different.
|
||||||
|
// We don't know how to decode it, so just compare them as byte
|
||||||
|
// slices.
|
||||||
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
|
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
|
||||||
continue
|
return false
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if m1 == nil {
|
if m1 == nil {
|
||||||
|
|||||||
+82
-126
@@ -38,6 +38,7 @@ package proto
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -91,14 +92,29 @@ func (n notLocker) Unlock() {}
|
|||||||
// extendable returns the extendableProto interface for the given generated proto message.
|
// extendable returns the extendableProto interface for the given generated proto message.
|
||||||
// If the proto message has the old extension format, it returns a wrapper that implements
|
// If the proto message has the old extension format, it returns a wrapper that implements
|
||||||
// the extendableProto interface.
|
// the extendableProto interface.
|
||||||
func extendable(p interface{}) (extendableProto, bool) {
|
func extendable(p interface{}) (extendableProto, error) {
|
||||||
if ep, ok := p.(extendableProto); ok {
|
switch p := p.(type) {
|
||||||
return ep, ok
|
case extendableProto:
|
||||||
|
if isNilPtr(p) {
|
||||||
|
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
case extendableProtoV1:
|
||||||
|
if isNilPtr(p) {
|
||||||
|
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
|
||||||
|
}
|
||||||
|
return extensionAdapter{p}, nil
|
||||||
}
|
}
|
||||||
if ep, ok := p.(extendableProtoV1); ok {
|
// Don't allocate a specific error containing %T:
|
||||||
return extensionAdapter{ep}, ok
|
// this is the hot path for Clone and MarshalText.
|
||||||
}
|
return nil, errNotExtendable
|
||||||
return nil, false
|
}
|
||||||
|
|
||||||
|
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
|
||||||
|
|
||||||
|
func isNilPtr(x interface{}) bool {
|
||||||
|
v := reflect.ValueOf(x)
|
||||||
|
return v.Kind() == reflect.Ptr && v.IsNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX_InternalExtensions is an internal representation of proto extensions.
|
// XXX_InternalExtensions is an internal representation of proto extensions.
|
||||||
@@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
|
|||||||
return e.p.extensionMap, &e.p.mu
|
return e.p.extensionMap, &e.p.mu
|
||||||
}
|
}
|
||||||
|
|
||||||
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
|
|
||||||
var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
|
|
||||||
|
|
||||||
// ExtensionDesc represents an extension specification.
|
// ExtensionDesc represents an extension specification.
|
||||||
// Used in generated code from the protocol compiler.
|
// Used in generated code from the protocol compiler.
|
||||||
type ExtensionDesc struct {
|
type ExtensionDesc struct {
|
||||||
@@ -179,8 +192,8 @@ type Extension struct {
|
|||||||
|
|
||||||
// SetRawExtension is for testing only.
|
// SetRawExtension is for testing only.
|
||||||
func SetRawExtension(base Message, id int32, b []byte) {
|
func SetRawExtension(base Message, id int32, b []byte) {
|
||||||
epb, ok := extendable(base)
|
epb, err := extendable(base)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
extmap := epb.extensionsWrite()
|
extmap := epb.extensionsWrite()
|
||||||
@@ -205,7 +218,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
|
|||||||
pbi = ea.extendableProtoV1
|
pbi = ea.extendableProtoV1
|
||||||
}
|
}
|
||||||
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
|
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
|
||||||
return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
|
return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
|
||||||
}
|
}
|
||||||
// Check the range.
|
// Check the range.
|
||||||
if !isExtensionField(pb, extension.Field) {
|
if !isExtensionField(pb, extension.Field) {
|
||||||
@@ -250,85 +263,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
|
|||||||
return prop
|
return prop
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode encodes any unmarshaled (unencoded) extensions in e.
|
|
||||||
func encodeExtensions(e *XXX_InternalExtensions) error {
|
|
||||||
m, mu := e.extensionsRead()
|
|
||||||
if m == nil {
|
|
||||||
return nil // fast path
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
return encodeExtensionsMap(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode encodes any unmarshaled (unencoded) extensions in e.
|
|
||||||
func encodeExtensionsMap(m map[int32]Extension) error {
|
|
||||||
for k, e := range m {
|
|
||||||
if e.value == nil || e.desc == nil {
|
|
||||||
// Extension is only in its encoded form.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't skip extensions that have an encoded form set,
|
|
||||||
// because the extension value may have been mutated after
|
|
||||||
// the last time this function was called.
|
|
||||||
|
|
||||||
et := reflect.TypeOf(e.desc.ExtensionType)
|
|
||||||
props := extensionProperties(e.desc)
|
|
||||||
|
|
||||||
p := NewBuffer(nil)
|
|
||||||
// If e.value has type T, the encoder expects a *struct{ X T }.
|
|
||||||
// Pass a *T with a zero field and hope it all works out.
|
|
||||||
x := reflect.New(et)
|
|
||||||
x.Elem().Set(reflect.ValueOf(e.value))
|
|
||||||
if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
e.enc = p.buf
|
|
||||||
m[k] = e
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extensionsSize(e *XXX_InternalExtensions) (n int) {
|
|
||||||
m, mu := e.extensionsRead()
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
return extensionsMapSize(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func extensionsMapSize(m map[int32]Extension) (n int) {
|
|
||||||
for _, e := range m {
|
|
||||||
if e.value == nil || e.desc == nil {
|
|
||||||
// Extension is only in its encoded form.
|
|
||||||
n += len(e.enc)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't skip extensions that have an encoded form set,
|
|
||||||
// because the extension value may have been mutated after
|
|
||||||
// the last time this function was called.
|
|
||||||
|
|
||||||
et := reflect.TypeOf(e.desc.ExtensionType)
|
|
||||||
props := extensionProperties(e.desc)
|
|
||||||
|
|
||||||
// If e.value has type T, the encoder expects a *struct{ X T }.
|
|
||||||
// Pass a *T with a zero field and hope it all works out.
|
|
||||||
x := reflect.New(et)
|
|
||||||
x.Elem().Set(reflect.ValueOf(e.value))
|
|
||||||
n += props.size(props, toStructPointer(x))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasExtension returns whether the given extension is present in pb.
|
// HasExtension returns whether the given extension is present in pb.
|
||||||
func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
||||||
// TODO: Check types, field numbers, etc.?
|
// TODO: Check types, field numbers, etc.?
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
extmap, mu := epb.extensionsRead()
|
extmap, mu := epb.extensionsRead()
|
||||||
@@ -336,15 +275,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
_, ok = extmap[extension.Field]
|
_, ok := extmap[extension.Field]
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearExtension removes the given extension from pb.
|
// ClearExtension removes the given extension from pb.
|
||||||
func ClearExtension(pb Message, extension *ExtensionDesc) {
|
func ClearExtension(pb Message, extension *ExtensionDesc) {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: Check types, field numbers, etc.?
|
// TODO: Check types, field numbers, etc.?
|
||||||
@@ -352,16 +291,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
|
|||||||
delete(extmap, extension.Field)
|
delete(extmap, extension.Field)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExtension parses and returns the given extension of pb.
|
// GetExtension retrieves a proto2 extended field from pb.
|
||||||
// If the extension is not present and has no default value it returns ErrMissingExtension.
|
//
|
||||||
|
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
||||||
|
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
||||||
|
// If the field is not present, then the default value is returned (if one is specified),
|
||||||
|
// otherwise ErrMissingExtension is reported.
|
||||||
|
//
|
||||||
|
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
|
||||||
|
// then GetExtension returns the raw encoded bytes of the field extension.
|
||||||
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, errors.New("proto: not an extendable proto")
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkExtensionTypes(epb, extension); err != nil {
|
if extension.ExtendedType != nil {
|
||||||
return nil, err
|
// can only check type if this is a complete descriptor
|
||||||
|
if err := checkExtensionTypes(epb, extension); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emap, mu := epb.extensionsRead()
|
emap, mu := epb.extensionsRead()
|
||||||
@@ -388,6 +337,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|||||||
return e.value, nil
|
return e.value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if extension.ExtensionType == nil {
|
||||||
|
// incomplete descriptor
|
||||||
|
return e.enc, nil
|
||||||
|
}
|
||||||
|
|
||||||
v, err := decodeExtension(e.enc, extension)
|
v, err := decodeExtension(e.enc, extension)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -405,6 +359,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|||||||
// defaultExtensionValue returns the default value for extension.
|
// defaultExtensionValue returns the default value for extension.
|
||||||
// If no default for an extension is defined ErrMissingExtension is returned.
|
// If no default for an extension is defined ErrMissingExtension is returned.
|
||||||
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
|
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
|
||||||
|
if extension.ExtensionType == nil {
|
||||||
|
// incomplete descriptor, so no default
|
||||||
|
return nil, ErrMissingExtension
|
||||||
|
}
|
||||||
|
|
||||||
t := reflect.TypeOf(extension.ExtensionType)
|
t := reflect.TypeOf(extension.ExtensionType)
|
||||||
props := extensionProperties(extension)
|
props := extensionProperties(extension)
|
||||||
|
|
||||||
@@ -439,31 +398,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
|
|||||||
|
|
||||||
// decodeExtension decodes an extension encoded in b.
|
// decodeExtension decodes an extension encoded in b.
|
||||||
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
||||||
o := NewBuffer(b)
|
|
||||||
|
|
||||||
t := reflect.TypeOf(extension.ExtensionType)
|
t := reflect.TypeOf(extension.ExtensionType)
|
||||||
|
unmarshal := typeUnmarshaler(t, extension.Tag)
|
||||||
props := extensionProperties(extension)
|
|
||||||
|
|
||||||
// t is a pointer to a struct, pointer to basic type or a slice.
|
// t is a pointer to a struct, pointer to basic type or a slice.
|
||||||
// Allocate a "field" to store the pointer/slice itself; the
|
// Allocate space to store the pointer/slice.
|
||||||
// pointer/slice will be stored here. We pass
|
|
||||||
// the address of this field to props.dec.
|
|
||||||
// This passes a zero field and a *t and lets props.dec
|
|
||||||
// interpret it as a *struct{ x t }.
|
|
||||||
value := reflect.New(t).Elem()
|
value := reflect.New(t).Elem()
|
||||||
|
|
||||||
|
var err error
|
||||||
for {
|
for {
|
||||||
// Discard wire type and field number varint. It isn't needed.
|
x, n := decodeVarint(b)
|
||||||
if _, err := o.DecodeVarint(); err != nil {
|
if n == 0 {
|
||||||
|
return nil, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b = b[n:]
|
||||||
|
wire := int(x) & 7
|
||||||
|
|
||||||
|
b, err = unmarshal(b, valToPointer(value.Addr()), wire)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
|
if len(b) == 0 {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.index >= len(o.buf) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -473,9 +429,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
|||||||
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
|
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
|
||||||
// The returned slice has the same length as es; missing extensions will appear as nil elements.
|
// The returned slice has the same length as es; missing extensions will appear as nil elements.
|
||||||
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
|
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, errors.New("proto: not an extendable proto")
|
return nil, err
|
||||||
}
|
}
|
||||||
extensions = make([]interface{}, len(es))
|
extensions = make([]interface{}, len(es))
|
||||||
for i, e := range es {
|
for i, e := range es {
|
||||||
@@ -494,9 +450,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
|
|||||||
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
|
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
|
||||||
// just the Field field, which defines the extension's field number.
|
// just the Field field, which defines the extension's field number.
|
||||||
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
|
return nil, err
|
||||||
}
|
}
|
||||||
registeredExtensions := RegisteredExtensions(pb)
|
registeredExtensions := RegisteredExtensions(pb)
|
||||||
|
|
||||||
@@ -523,9 +479,9 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
|||||||
|
|
||||||
// SetExtension sets the specified extension of pb to the specified value.
|
// SetExtension sets the specified extension of pb to the specified value.
|
||||||
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
|
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return errors.New("proto: not an extendable proto")
|
return err
|
||||||
}
|
}
|
||||||
if err := checkExtensionTypes(epb, extension); err != nil {
|
if err := checkExtensionTypes(epb, extension); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -550,8 +506,8 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
|
|||||||
|
|
||||||
// ClearAllExtensions clears all extensions from pb.
|
// ClearAllExtensions clears all extensions from pb.
|
||||||
func ClearAllExtensions(pb Message) {
|
func ClearAllExtensions(pb Message) {
|
||||||
epb, ok := extendable(pb)
|
epb, err := extendable(pb)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := epb.extensionsWrite()
|
m := epb.extensionsWrite()
|
||||||
|
|||||||
+47
-23
@@ -265,6 +265,7 @@ package proto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -273,6 +274,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
|
||||||
|
|
||||||
// Message is implemented by generated protocol buffer messages.
|
// Message is implemented by generated protocol buffer messages.
|
||||||
type Message interface {
|
type Message interface {
|
||||||
Reset()
|
Reset()
|
||||||
@@ -309,16 +312,7 @@ type Buffer struct {
|
|||||||
buf []byte // encode/decode byte stream
|
buf []byte // encode/decode byte stream
|
||||||
index int // read point
|
index int // read point
|
||||||
|
|
||||||
// pools of basic types to amortize allocation.
|
deterministic bool
|
||||||
bools []bool
|
|
||||||
uint32s []uint32
|
|
||||||
uint64s []uint64
|
|
||||||
|
|
||||||
// extra pools, only used with pointer_reflect.go
|
|
||||||
int32s []int32
|
|
||||||
int64s []int64
|
|
||||||
float32s []float32
|
|
||||||
float64s []float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuffer allocates a new Buffer and initializes its internal data to
|
// NewBuffer allocates a new Buffer and initializes its internal data to
|
||||||
@@ -343,6 +337,30 @@ func (p *Buffer) SetBuf(s []byte) {
|
|||||||
// Bytes returns the contents of the Buffer.
|
// Bytes returns the contents of the Buffer.
|
||||||
func (p *Buffer) Bytes() []byte { return p.buf }
|
func (p *Buffer) Bytes() []byte { return p.buf }
|
||||||
|
|
||||||
|
// SetDeterministic sets whether to use deterministic serialization.
|
||||||
|
//
|
||||||
|
// Deterministic serialization guarantees that for a given binary, equal
|
||||||
|
// messages will always be serialized to the same bytes. This implies:
|
||||||
|
//
|
||||||
|
// - Repeated serialization of a message will return the same bytes.
|
||||||
|
// - Different processes of the same binary (which may be executing on
|
||||||
|
// different machines) will serialize equal messages to the same bytes.
|
||||||
|
//
|
||||||
|
// Note that the deterministic serialization is NOT canonical across
|
||||||
|
// languages. It is not guaranteed to remain stable over time. It is unstable
|
||||||
|
// across different builds with schema changes due to unknown fields.
|
||||||
|
// Users who need canonical serialization (e.g., persistent storage in a
|
||||||
|
// canonical form, fingerprinting, etc.) should define their own
|
||||||
|
// canonicalization specification and implement their own serializer rather
|
||||||
|
// than relying on this API.
|
||||||
|
//
|
||||||
|
// If deterministic serialization is requested, map entries will be sorted
|
||||||
|
// by keys in lexographical order. This is an implementation detail and
|
||||||
|
// subject to change.
|
||||||
|
func (p *Buffer) SetDeterministic(deterministic bool) {
|
||||||
|
p.deterministic = deterministic
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
* Helper routines for simplifying the creation of optional fields of basic type.
|
||||||
*/
|
*/
|
||||||
@@ -831,22 +849,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
|
|||||||
return sf, false, nil
|
return sf, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mapKeys returns a sort.Interface to be used for sorting the map keys.
|
||||||
// Map fields may have key types of non-float scalars, strings and enums.
|
// Map fields may have key types of non-float scalars, strings and enums.
|
||||||
// The easiest way to sort them in some deterministic order is to use fmt.
|
|
||||||
// If this turns out to be inefficient we can always consider other options,
|
|
||||||
// such as doing a Schwartzian transform.
|
|
||||||
|
|
||||||
func mapKeys(vs []reflect.Value) sort.Interface {
|
func mapKeys(vs []reflect.Value) sort.Interface {
|
||||||
s := mapKeySorter{
|
s := mapKeySorter{vs: vs}
|
||||||
vs: vs,
|
|
||||||
// default Less function: textual comparison
|
|
||||||
less: func(a, b reflect.Value) bool {
|
|
||||||
return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
|
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
|
||||||
// numeric keys are sorted numerically.
|
|
||||||
if len(vs) == 0 {
|
if len(vs) == 0 {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -855,6 +863,12 @@ func mapKeys(vs []reflect.Value) sort.Interface {
|
|||||||
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
|
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
|
||||||
case reflect.Uint32, reflect.Uint64:
|
case reflect.Uint32, reflect.Uint64:
|
||||||
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
|
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
|
||||||
|
case reflect.Bool:
|
||||||
|
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
|
||||||
|
case reflect.String:
|
||||||
|
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -895,3 +909,13 @@ const ProtoPackageIsVersion2 = true
|
|||||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
// to assert that that code is compatible with this version of the proto package.
|
||||||
const ProtoPackageIsVersion1 = true
|
const ProtoPackageIsVersion1 = true
|
||||||
|
|
||||||
|
// InternalMessageInfo is a type used internally by generated .pb.go files.
|
||||||
|
// This type is not intended to be used by non-generated code.
|
||||||
|
// This type is not subject to any compatibility guarantee.
|
||||||
|
type InternalMessageInfo struct {
|
||||||
|
marshal *marshalInfo
|
||||||
|
unmarshal *unmarshalInfo
|
||||||
|
merge *mergeInfo
|
||||||
|
discard *discardInfo
|
||||||
|
}
|
||||||
|
|||||||
+42
-39
@@ -42,6 +42,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
||||||
@@ -94,10 +95,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ms *messageSet) Has(pb Message) bool {
|
func (ms *messageSet) Has(pb Message) bool {
|
||||||
if ms.find(pb) != nil {
|
return ms.find(pb) != nil
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *messageSet) Unmarshal(pb Message) error {
|
func (ms *messageSet) Unmarshal(pb Message) error {
|
||||||
@@ -150,46 +148,42 @@ func skipVarint(buf []byte) []byte {
|
|||||||
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
|
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
|
||||||
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
|
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||||
func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
||||||
var m map[int32]Extension
|
return marshalMessageSet(exts, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
|
||||||
|
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
|
||||||
switch exts := exts.(type) {
|
switch exts := exts.(type) {
|
||||||
case *XXX_InternalExtensions:
|
case *XXX_InternalExtensions:
|
||||||
if err := encodeExtensions(exts); err != nil {
|
var u marshalInfo
|
||||||
return nil, err
|
siz := u.sizeMessageSet(exts)
|
||||||
}
|
b := make([]byte, 0, siz)
|
||||||
m, _ = exts.extensionsRead()
|
return u.appendMessageSet(b, exts, deterministic)
|
||||||
|
|
||||||
case map[int32]Extension:
|
case map[int32]Extension:
|
||||||
if err := encodeExtensionsMap(exts); err != nil {
|
// This is an old-style extension map.
|
||||||
return nil, err
|
// Wrap it in a new-style XXX_InternalExtensions.
|
||||||
|
ie := XXX_InternalExtensions{
|
||||||
|
p: &struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
extensionMap map[int32]Extension
|
||||||
|
}{
|
||||||
|
extensionMap: exts,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
m = exts
|
|
||||||
|
var u marshalInfo
|
||||||
|
siz := u.sizeMessageSet(&ie)
|
||||||
|
b := make([]byte, 0, siz)
|
||||||
|
return u.appendMessageSet(b, &ie, deterministic)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("proto: not an extension map")
|
return nil, errors.New("proto: not an extension map")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort extension IDs to provide a deterministic encoding.
|
|
||||||
// See also enc_map in encode.go.
|
|
||||||
ids := make([]int, 0, len(m))
|
|
||||||
for id := range m {
|
|
||||||
ids = append(ids, int(id))
|
|
||||||
}
|
|
||||||
sort.Ints(ids)
|
|
||||||
|
|
||||||
ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
|
|
||||||
for _, id := range ids {
|
|
||||||
e := m[int32(id)]
|
|
||||||
// Remove the wire type and field number varint, as well as the length varint.
|
|
||||||
msg := skipVarint(skipVarint(e.enc))
|
|
||||||
|
|
||||||
ms.Item = append(ms.Item, &_MessageSet_Item{
|
|
||||||
TypeId: Int32(int32(id)),
|
|
||||||
Message: msg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return Marshal(ms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
||||||
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||||
var m map[int32]Extension
|
var m map[int32]Extension
|
||||||
switch exts := exts.(type) {
|
switch exts := exts.(type) {
|
||||||
@@ -235,7 +229,15 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
|||||||
var m map[int32]Extension
|
var m map[int32]Extension
|
||||||
switch exts := exts.(type) {
|
switch exts := exts.(type) {
|
||||||
case *XXX_InternalExtensions:
|
case *XXX_InternalExtensions:
|
||||||
m, _ = exts.extensionsRead()
|
var mu sync.Locker
|
||||||
|
m, mu = exts.extensionsRead()
|
||||||
|
if m != nil {
|
||||||
|
// Keep the extensions map locked until we're done marshaling to prevent
|
||||||
|
// races between marshaling and unmarshaling the lazily-{en,de}coded
|
||||||
|
// values.
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
}
|
||||||
case map[int32]Extension:
|
case map[int32]Extension:
|
||||||
m = exts
|
m = exts
|
||||||
default:
|
default:
|
||||||
@@ -253,15 +255,16 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
|||||||
|
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
ext := m[id]
|
ext := m[id]
|
||||||
if i > 0 {
|
|
||||||
b.WriteByte(',')
|
|
||||||
}
|
|
||||||
|
|
||||||
msd, ok := messageSetMap[id]
|
msd, ok := messageSetMap[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Unknown type; we can't render it, so skip it.
|
// Unknown type; we can't render it, so skip it.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if i > 0 && b.Len() > 1 {
|
||||||
|
b.WriteByte(',')
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(&b, `"[%s]":`, msd.name)
|
fmt.Fprintf(&b, `"[%s]":`, msd.name)
|
||||||
|
|
||||||
x := ext.value
|
x := ext.value
|
||||||
|
|||||||
+259
-386
@@ -29,7 +29,7 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// +build appengine js
|
// +build purego appengine js
|
||||||
|
|
||||||
// This file contains an implementation of proto field accesses using package reflect.
|
// This file contains an implementation of proto field accesses using package reflect.
|
||||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
|
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
|
||||||
@@ -38,32 +38,13 @@
|
|||||||
package proto
|
package proto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A structPointer is a pointer to a struct.
|
const unsafeAllowed = false
|
||||||
type structPointer struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// toStructPointer returns a structPointer equivalent to the given reflect value.
|
// A field identifies a field in a struct, accessible from a pointer.
|
||||||
// The reflect value must itself be a pointer to a struct.
|
|
||||||
func toStructPointer(v reflect.Value) structPointer {
|
|
||||||
return structPointer{v}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNil reports whether p is nil.
|
|
||||||
func structPointer_IsNil(p structPointer) bool {
|
|
||||||
return p.v.IsNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interface returns the struct pointer as an interface value.
|
|
||||||
func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
|
|
||||||
return p.v.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a structPointer.
|
|
||||||
// In this implementation, a field is identified by the sequence of field indices
|
// In this implementation, a field is identified by the sequence of field indices
|
||||||
// passed to reflect's FieldByIndex.
|
// passed to reflect's FieldByIndex.
|
||||||
type field []int
|
type field []int
|
||||||
@@ -76,409 +57,301 @@ func toField(f *reflect.StructField) field {
|
|||||||
// invalidField is an invalid field identifier.
|
// invalidField is an invalid field identifier.
|
||||||
var invalidField = field(nil)
|
var invalidField = field(nil)
|
||||||
|
|
||||||
|
// zeroField is a noop when calling pointer.offset.
|
||||||
|
var zeroField = field([]int{})
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
// IsValid reports whether the field identifier is valid.
|
||||||
func (f field) IsValid() bool { return f != nil }
|
func (f field) IsValid() bool { return f != nil }
|
||||||
|
|
||||||
// field returns the given field in the struct as a reflect value.
|
// The pointer type is for the table-driven decoder.
|
||||||
func structPointer_field(p structPointer, f field) reflect.Value {
|
// The implementation here uses a reflect.Value of pointer type to
|
||||||
// Special case: an extension map entry with a value of type T
|
// create a generic pointer. In pointer_unsafe.go we use unsafe
|
||||||
// passes a *T to the struct-handling code with a zero field,
|
// instead of reflect to implement the same (but faster) interface.
|
||||||
// expecting that it will be treated as equivalent to *struct{ X T },
|
type pointer struct {
|
||||||
// which has the same memory layout. We have to handle that case
|
|
||||||
// specially, because reflect will panic if we call FieldByIndex on a
|
|
||||||
// non-struct.
|
|
||||||
if f == nil {
|
|
||||||
return p.v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.v.Elem().FieldByIndex(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ifield returns the given field in the struct as an interface value.
|
|
||||||
func structPointer_ifield(p structPointer, f field) interface{} {
|
|
||||||
return structPointer_field(p, f).Addr().Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the address of a []byte field in the struct.
|
|
||||||
func structPointer_Bytes(p structPointer, f field) *[]byte {
|
|
||||||
return structPointer_ifield(p, f).(*[]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BytesSlice returns the address of a [][]byte field in the struct.
|
|
||||||
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
|
|
||||||
return structPointer_ifield(p, f).(*[][]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool returns the address of a *bool field in the struct.
|
|
||||||
func structPointer_Bool(p structPointer, f field) **bool {
|
|
||||||
return structPointer_ifield(p, f).(**bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolVal returns the address of a bool field in the struct.
|
|
||||||
func structPointer_BoolVal(p structPointer, f field) *bool {
|
|
||||||
return structPointer_ifield(p, f).(*bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSlice returns the address of a []bool field in the struct.
|
|
||||||
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
|
|
||||||
return structPointer_ifield(p, f).(*[]bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the address of a *string field in the struct.
|
|
||||||
func structPointer_String(p structPointer, f field) **string {
|
|
||||||
return structPointer_ifield(p, f).(**string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVal returns the address of a string field in the struct.
|
|
||||||
func structPointer_StringVal(p structPointer, f field) *string {
|
|
||||||
return structPointer_ifield(p, f).(*string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice returns the address of a []string field in the struct.
|
|
||||||
func structPointer_StringSlice(p structPointer, f field) *[]string {
|
|
||||||
return structPointer_ifield(p, f).(*[]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extensions returns the address of an extension map field in the struct.
|
|
||||||
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
||||||
return structPointer_ifield(p, f).(*XXX_InternalExtensions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtMap returns the address of an extension map field in the struct.
|
|
||||||
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
|
||||||
return structPointer_ifield(p, f).(*map[int32]Extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAt returns the reflect.Value for a pointer to a field in the struct.
|
|
||||||
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
|
|
||||||
return structPointer_field(p, f).Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetStructPointer writes a *struct field in the struct.
|
|
||||||
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
|
|
||||||
structPointer_field(p, f).Set(q.v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStructPointer reads a *struct field in the struct.
|
|
||||||
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
|
|
||||||
return structPointer{structPointer_field(p, f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StructPointerSlice the address of a []*struct field in the struct.
|
|
||||||
func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
|
|
||||||
return structPointerSlice{structPointer_field(p, f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A structPointerSlice represents the address of a slice of pointers to structs
|
|
||||||
// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
|
|
||||||
type structPointerSlice struct {
|
|
||||||
v reflect.Value
|
v reflect.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p structPointerSlice) Len() int { return p.v.Len() }
|
// toPointer converts an interface of pointer type to a pointer
|
||||||
func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
|
// that points to the same target.
|
||||||
func (p structPointerSlice) Append(q structPointer) {
|
func toPointer(i *Message) pointer {
|
||||||
p.v.Set(reflect.Append(p.v, q.v))
|
return pointer{v: reflect.ValueOf(*i)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
// toAddrPointer converts an interface to a pointer that points to
|
||||||
int32Type = reflect.TypeOf(int32(0))
|
// the interface data.
|
||||||
uint32Type = reflect.TypeOf(uint32(0))
|
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||||
float32Type = reflect.TypeOf(float32(0))
|
v := reflect.ValueOf(*i)
|
||||||
int64Type = reflect.TypeOf(int64(0))
|
u := reflect.New(v.Type())
|
||||||
uint64Type = reflect.TypeOf(uint64(0))
|
u.Elem().Set(v)
|
||||||
float64Type = reflect.TypeOf(float64(0))
|
return pointer{v: u}
|
||||||
)
|
|
||||||
|
|
||||||
// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
|
|
||||||
// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
|
|
||||||
type word32 struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNil reports whether p is nil.
|
// valToPointer converts v to a pointer. v must be of pointer type.
|
||||||
func word32_IsNil(p word32) bool {
|
func valToPointer(v reflect.Value) pointer {
|
||||||
|
return pointer{v: v}
|
||||||
|
}
|
||||||
|
|
||||||
|
// offset converts from a pointer to a structure to a pointer to
|
||||||
|
// one of its fields.
|
||||||
|
func (p pointer) offset(f field) pointer {
|
||||||
|
return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pointer) isNil() bool {
|
||||||
return p.v.IsNil()
|
return p.v.IsNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets p to point at a newly allocated word with bits set to x.
|
// grow updates the slice s in place to make it one element longer.
|
||||||
func word32_Set(p word32, o *Buffer, x uint32) {
|
// s must be addressable.
|
||||||
t := p.v.Type().Elem()
|
// Returns the (addressable) new element.
|
||||||
switch t {
|
func grow(s reflect.Value) reflect.Value {
|
||||||
case int32Type:
|
n, m := s.Len(), s.Cap()
|
||||||
if len(o.int32s) == 0 {
|
|
||||||
o.int32s = make([]int32, uint32PoolSize)
|
|
||||||
}
|
|
||||||
o.int32s[0] = int32(x)
|
|
||||||
p.v.Set(reflect.ValueOf(&o.int32s[0]))
|
|
||||||
o.int32s = o.int32s[1:]
|
|
||||||
return
|
|
||||||
case uint32Type:
|
|
||||||
if len(o.uint32s) == 0 {
|
|
||||||
o.uint32s = make([]uint32, uint32PoolSize)
|
|
||||||
}
|
|
||||||
o.uint32s[0] = x
|
|
||||||
p.v.Set(reflect.ValueOf(&o.uint32s[0]))
|
|
||||||
o.uint32s = o.uint32s[1:]
|
|
||||||
return
|
|
||||||
case float32Type:
|
|
||||||
if len(o.float32s) == 0 {
|
|
||||||
o.float32s = make([]float32, uint32PoolSize)
|
|
||||||
}
|
|
||||||
o.float32s[0] = math.Float32frombits(x)
|
|
||||||
p.v.Set(reflect.ValueOf(&o.float32s[0]))
|
|
||||||
o.float32s = o.float32s[1:]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// must be enum
|
|
||||||
p.v.Set(reflect.New(t))
|
|
||||||
p.v.Elem().SetInt(int64(int32(x)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets the bits pointed at by p, as a uint32.
|
|
||||||
func word32_Get(p word32) uint32 {
|
|
||||||
elem := p.v.Elem()
|
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int32:
|
|
||||||
return uint32(elem.Int())
|
|
||||||
case reflect.Uint32:
|
|
||||||
return uint32(elem.Uint())
|
|
||||||
case reflect.Float32:
|
|
||||||
return math.Float32bits(float32(elem.Float()))
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
|
|
||||||
func structPointer_Word32(p structPointer, f field) word32 {
|
|
||||||
return word32{structPointer_field(p, f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A word32Val represents a field of type int32, uint32, float32, or enum.
|
|
||||||
// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
|
|
||||||
type word32Val struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets *p to x.
|
|
||||||
func word32Val_Set(p word32Val, x uint32) {
|
|
||||||
switch p.v.Type() {
|
|
||||||
case int32Type:
|
|
||||||
p.v.SetInt(int64(x))
|
|
||||||
return
|
|
||||||
case uint32Type:
|
|
||||||
p.v.SetUint(uint64(x))
|
|
||||||
return
|
|
||||||
case float32Type:
|
|
||||||
p.v.SetFloat(float64(math.Float32frombits(x)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// must be enum
|
|
||||||
p.v.SetInt(int64(int32(x)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets the bits pointed at by p, as a uint32.
|
|
||||||
func word32Val_Get(p word32Val) uint32 {
|
|
||||||
elem := p.v
|
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int32:
|
|
||||||
return uint32(elem.Int())
|
|
||||||
case reflect.Uint32:
|
|
||||||
return uint32(elem.Uint())
|
|
||||||
case reflect.Float32:
|
|
||||||
return math.Float32bits(float32(elem.Float()))
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
|
|
||||||
func structPointer_Word32Val(p structPointer, f field) word32Val {
|
|
||||||
return word32Val{structPointer_field(p, f)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A word32Slice is a slice of 32-bit values.
|
|
||||||
// That is, v.Type() is []int32, []uint32, []float32, or []enum.
|
|
||||||
type word32Slice struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p word32Slice) Append(x uint32) {
|
|
||||||
n, m := p.v.Len(), p.v.Cap()
|
|
||||||
if n < m {
|
if n < m {
|
||||||
p.v.SetLen(n + 1)
|
s.SetLen(n + 1)
|
||||||
} else {
|
} else {
|
||||||
t := p.v.Type().Elem()
|
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
|
||||||
p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
|
|
||||||
}
|
}
|
||||||
elem := p.v.Index(n)
|
return s.Index(n)
|
||||||
switch elem.Kind() {
|
}
|
||||||
case reflect.Int32:
|
|
||||||
elem.SetInt(int64(int32(x)))
|
func (p pointer) toInt64() *int64 {
|
||||||
case reflect.Uint32:
|
return p.v.Interface().(*int64)
|
||||||
elem.SetUint(uint64(x))
|
}
|
||||||
case reflect.Float32:
|
func (p pointer) toInt64Ptr() **int64 {
|
||||||
elem.SetFloat(float64(math.Float32frombits(x)))
|
return p.v.Interface().(**int64)
|
||||||
|
}
|
||||||
|
func (p pointer) toInt64Slice() *[]int64 {
|
||||||
|
return p.v.Interface().(*[]int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
var int32ptr = reflect.TypeOf((*int32)(nil))
|
||||||
|
|
||||||
|
func (p pointer) toInt32() *int32 {
|
||||||
|
return p.v.Convert(int32ptr).Interface().(*int32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The toInt32Ptr/Slice methods don't work because of enums.
|
||||||
|
// Instead, we must use set/get methods for the int32ptr/slice case.
|
||||||
|
/*
|
||||||
|
func (p pointer) toInt32Ptr() **int32 {
|
||||||
|
return p.v.Interface().(**int32)
|
||||||
|
}
|
||||||
|
func (p pointer) toInt32Slice() *[]int32 {
|
||||||
|
return p.v.Interface().(*[]int32)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
func (p pointer) getInt32Ptr() *int32 {
|
||||||
|
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
||||||
|
// raw int32 type
|
||||||
|
return p.v.Elem().Interface().(*int32)
|
||||||
}
|
}
|
||||||
|
// an enum
|
||||||
|
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
|
||||||
|
}
|
||||||
|
func (p pointer) setInt32Ptr(v int32) {
|
||||||
|
// Allocate value in a *int32. Possibly convert that to a *enum.
|
||||||
|
// Then assign it to a **int32 or **enum.
|
||||||
|
// Note: we can convert *int32 to *enum, but we can't convert
|
||||||
|
// **int32 to **enum!
|
||||||
|
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p word32Slice) Len() int {
|
// getInt32Slice copies []int32 from p as a new slice.
|
||||||
return p.v.Len()
|
// This behavior differs from the implementation in pointer_unsafe.go.
|
||||||
}
|
func (p pointer) getInt32Slice() []int32 {
|
||||||
|
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
||||||
func (p word32Slice) Index(i int) uint32 {
|
// raw int32 type
|
||||||
elem := p.v.Index(i)
|
return p.v.Elem().Interface().([]int32)
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int32:
|
|
||||||
return uint32(elem.Int())
|
|
||||||
case reflect.Uint32:
|
|
||||||
return uint32(elem.Uint())
|
|
||||||
case reflect.Float32:
|
|
||||||
return math.Float32bits(float32(elem.Float()))
|
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
// an enum
|
||||||
|
// Allocate a []int32, then assign []enum's values into it.
|
||||||
|
// Note: we can't convert []enum to []int32.
|
||||||
|
slice := p.v.Elem()
|
||||||
|
s := make([]int32, slice.Len())
|
||||||
|
for i := 0; i < slice.Len(); i++ {
|
||||||
|
s[i] = int32(slice.Index(i).Int())
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
|
// setInt32Slice copies []int32 into p as a new slice.
|
||||||
func structPointer_Word32Slice(p structPointer, f field) word32Slice {
|
// This behavior differs from the implementation in pointer_unsafe.go.
|
||||||
return word32Slice{structPointer_field(p, f)}
|
func (p pointer) setInt32Slice(v []int32) {
|
||||||
}
|
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
||||||
|
// raw int32 type
|
||||||
// word64 is like word32 but for 64-bit values.
|
p.v.Elem().Set(reflect.ValueOf(v))
|
||||||
type word64 struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func word64_Set(p word64, o *Buffer, x uint64) {
|
|
||||||
t := p.v.Type().Elem()
|
|
||||||
switch t {
|
|
||||||
case int64Type:
|
|
||||||
if len(o.int64s) == 0 {
|
|
||||||
o.int64s = make([]int64, uint64PoolSize)
|
|
||||||
}
|
|
||||||
o.int64s[0] = int64(x)
|
|
||||||
p.v.Set(reflect.ValueOf(&o.int64s[0]))
|
|
||||||
o.int64s = o.int64s[1:]
|
|
||||||
return
|
|
||||||
case uint64Type:
|
|
||||||
if len(o.uint64s) == 0 {
|
|
||||||
o.uint64s = make([]uint64, uint64PoolSize)
|
|
||||||
}
|
|
||||||
o.uint64s[0] = x
|
|
||||||
p.v.Set(reflect.ValueOf(&o.uint64s[0]))
|
|
||||||
o.uint64s = o.uint64s[1:]
|
|
||||||
return
|
|
||||||
case float64Type:
|
|
||||||
if len(o.float64s) == 0 {
|
|
||||||
o.float64s = make([]float64, uint64PoolSize)
|
|
||||||
}
|
|
||||||
o.float64s[0] = math.Float64frombits(x)
|
|
||||||
p.v.Set(reflect.ValueOf(&o.float64s[0]))
|
|
||||||
o.float64s = o.float64s[1:]
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
// an enum
|
||||||
}
|
// Allocate a []enum, then assign []int32's values into it.
|
||||||
|
// Note: we can't convert []enum to []int32.
|
||||||
func word64_IsNil(p word64) bool {
|
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
|
||||||
return p.v.IsNil()
|
for i, x := range v {
|
||||||
}
|
slice.Index(i).SetInt(int64(x))
|
||||||
|
|
||||||
func word64_Get(p word64) uint64 {
|
|
||||||
elem := p.v.Elem()
|
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int64:
|
|
||||||
return uint64(elem.Int())
|
|
||||||
case reflect.Uint64:
|
|
||||||
return elem.Uint()
|
|
||||||
case reflect.Float64:
|
|
||||||
return math.Float64bits(elem.Float())
|
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
p.v.Elem().Set(slice)
|
||||||
|
}
|
||||||
|
func (p pointer) appendInt32Slice(v int32) {
|
||||||
|
grow(p.v.Elem()).SetInt(int64(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Word64(p structPointer, f field) word64 {
|
func (p pointer) toUint64() *uint64 {
|
||||||
return word64{structPointer_field(p, f)}
|
return p.v.Interface().(*uint64)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint64Ptr() **uint64 {
|
||||||
|
return p.v.Interface().(**uint64)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint64Slice() *[]uint64 {
|
||||||
|
return p.v.Interface().(*[]uint64)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32() *uint32 {
|
||||||
|
return p.v.Interface().(*uint32)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32Ptr() **uint32 {
|
||||||
|
return p.v.Interface().(**uint32)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32Slice() *[]uint32 {
|
||||||
|
return p.v.Interface().(*[]uint32)
|
||||||
|
}
|
||||||
|
func (p pointer) toBool() *bool {
|
||||||
|
return p.v.Interface().(*bool)
|
||||||
|
}
|
||||||
|
func (p pointer) toBoolPtr() **bool {
|
||||||
|
return p.v.Interface().(**bool)
|
||||||
|
}
|
||||||
|
func (p pointer) toBoolSlice() *[]bool {
|
||||||
|
return p.v.Interface().(*[]bool)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64() *float64 {
|
||||||
|
return p.v.Interface().(*float64)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64Ptr() **float64 {
|
||||||
|
return p.v.Interface().(**float64)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64Slice() *[]float64 {
|
||||||
|
return p.v.Interface().(*[]float64)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32() *float32 {
|
||||||
|
return p.v.Interface().(*float32)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32Ptr() **float32 {
|
||||||
|
return p.v.Interface().(**float32)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32Slice() *[]float32 {
|
||||||
|
return p.v.Interface().(*[]float32)
|
||||||
|
}
|
||||||
|
func (p pointer) toString() *string {
|
||||||
|
return p.v.Interface().(*string)
|
||||||
|
}
|
||||||
|
func (p pointer) toStringPtr() **string {
|
||||||
|
return p.v.Interface().(**string)
|
||||||
|
}
|
||||||
|
func (p pointer) toStringSlice() *[]string {
|
||||||
|
return p.v.Interface().(*[]string)
|
||||||
|
}
|
||||||
|
func (p pointer) toBytes() *[]byte {
|
||||||
|
return p.v.Interface().(*[]byte)
|
||||||
|
}
|
||||||
|
func (p pointer) toBytesSlice() *[][]byte {
|
||||||
|
return p.v.Interface().(*[][]byte)
|
||||||
|
}
|
||||||
|
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
||||||
|
return p.v.Interface().(*XXX_InternalExtensions)
|
||||||
|
}
|
||||||
|
func (p pointer) toOldExtensions() *map[int32]Extension {
|
||||||
|
return p.v.Interface().(*map[int32]Extension)
|
||||||
|
}
|
||||||
|
func (p pointer) getPointer() pointer {
|
||||||
|
return pointer{v: p.v.Elem()}
|
||||||
|
}
|
||||||
|
func (p pointer) setPointer(q pointer) {
|
||||||
|
p.v.Elem().Set(q.v)
|
||||||
|
}
|
||||||
|
func (p pointer) appendPointer(q pointer) {
|
||||||
|
grow(p.v.Elem()).Set(q.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// word64Val is like word32Val but for 64-bit values.
|
// getPointerSlice copies []*T from p as a new []pointer.
|
||||||
type word64Val struct {
|
// This behavior differs from the implementation in pointer_unsafe.go.
|
||||||
v reflect.Value
|
func (p pointer) getPointerSlice() []pointer {
|
||||||
|
if p.v.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
n := p.v.Elem().Len()
|
||||||
|
s := make([]pointer, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
s[i] = pointer{v: p.v.Elem().Index(i)}
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
|
// setPointerSlice copies []pointer into p as a new []*T.
|
||||||
switch p.v.Type() {
|
// This behavior differs from the implementation in pointer_unsafe.go.
|
||||||
case int64Type:
|
func (p pointer) setPointerSlice(v []pointer) {
|
||||||
p.v.SetInt(int64(x))
|
if v == nil {
|
||||||
return
|
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
|
||||||
case uint64Type:
|
|
||||||
p.v.SetUint(x)
|
|
||||||
return
|
|
||||||
case float64Type:
|
|
||||||
p.v.SetFloat(math.Float64frombits(x))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
|
||||||
}
|
for _, p := range v {
|
||||||
|
s = reflect.Append(s, p.v)
|
||||||
func word64Val_Get(p word64Val) uint64 {
|
|
||||||
elem := p.v
|
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int64:
|
|
||||||
return uint64(elem.Int())
|
|
||||||
case reflect.Uint64:
|
|
||||||
return elem.Uint()
|
|
||||||
case reflect.Float64:
|
|
||||||
return math.Float64bits(elem.Float())
|
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
p.v.Elem().Set(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Word64Val(p structPointer, f field) word64Val {
|
// getInterfacePointer returns a pointer that points to the
|
||||||
return word64Val{structPointer_field(p, f)}
|
// interface data of the interface pointed by p.
|
||||||
}
|
func (p pointer) getInterfacePointer() pointer {
|
||||||
|
if p.v.Elem().IsNil() {
|
||||||
type word64Slice struct {
|
return pointer{v: p.v.Elem()}
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p word64Slice) Append(x uint64) {
|
|
||||||
n, m := p.v.Len(), p.v.Cap()
|
|
||||||
if n < m {
|
|
||||||
p.v.SetLen(n + 1)
|
|
||||||
} else {
|
|
||||||
t := p.v.Type().Elem()
|
|
||||||
p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
|
|
||||||
}
|
|
||||||
elem := p.v.Index(n)
|
|
||||||
switch elem.Kind() {
|
|
||||||
case reflect.Int64:
|
|
||||||
elem.SetInt(int64(int64(x)))
|
|
||||||
case reflect.Uint64:
|
|
||||||
elem.SetUint(uint64(x))
|
|
||||||
case reflect.Float64:
|
|
||||||
elem.SetFloat(float64(math.Float64frombits(x)))
|
|
||||||
}
|
}
|
||||||
|
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p word64Slice) Len() int {
|
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
||||||
return p.v.Len()
|
// TODO: check that p.v.Type().Elem() == t?
|
||||||
|
return p.v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p word64Slice) Index(i int) uint64 {
|
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
||||||
elem := p.v.Index(i)
|
atomicLock.Lock()
|
||||||
switch elem.Kind() {
|
defer atomicLock.Unlock()
|
||||||
case reflect.Int64:
|
return *p
|
||||||
return uint64(elem.Int())
|
}
|
||||||
case reflect.Uint64:
|
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
||||||
return uint64(elem.Uint())
|
atomicLock.Lock()
|
||||||
case reflect.Float64:
|
defer atomicLock.Unlock()
|
||||||
return math.Float64bits(float64(elem.Float()))
|
*p = v
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
return *p
|
||||||
|
}
|
||||||
|
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
*p = v
|
||||||
|
}
|
||||||
|
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
return *p
|
||||||
|
}
|
||||||
|
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
*p = v
|
||||||
|
}
|
||||||
|
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
return *p
|
||||||
|
}
|
||||||
|
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
||||||
|
atomicLock.Lock()
|
||||||
|
defer atomicLock.Unlock()
|
||||||
|
*p = v
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Word64Slice(p structPointer, f field) word64Slice {
|
var atomicLock sync.Mutex
|
||||||
return word64Slice{structPointer_field(p, f)}
|
|
||||||
}
|
|
||||||
|
|||||||
+220
-182
@@ -29,7 +29,7 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// +build !appengine,!js
|
// +build !purego,!appengine,!js
|
||||||
|
|
||||||
// This file contains the implementation of the proto field accesses using package unsafe.
|
// This file contains the implementation of the proto field accesses using package unsafe.
|
||||||
|
|
||||||
@@ -37,38 +37,13 @@ package proto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync/atomic"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: These type_Foo functions would more idiomatically be methods,
|
const unsafeAllowed = true
|
||||||
// but Go does not allow methods on pointer types, and we must preserve
|
|
||||||
// some pointer type for the garbage collector. We use these
|
|
||||||
// funcs with clunky names as our poor approximation to methods.
|
|
||||||
//
|
|
||||||
// An alternative would be
|
|
||||||
// type structPointer struct { p unsafe.Pointer }
|
|
||||||
// but that does not registerize as well.
|
|
||||||
|
|
||||||
// A structPointer is a pointer to a struct.
|
// A field identifies a field in a struct, accessible from a pointer.
|
||||||
type structPointer unsafe.Pointer
|
|
||||||
|
|
||||||
// toStructPointer returns a structPointer equivalent to the given reflect value.
|
|
||||||
func toStructPointer(v reflect.Value) structPointer {
|
|
||||||
return structPointer(unsafe.Pointer(v.Pointer()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNil reports whether p is nil.
|
|
||||||
func structPointer_IsNil(p structPointer) bool {
|
|
||||||
return p == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interface returns the struct pointer, assumed to have element type t,
|
|
||||||
// as an interface value.
|
|
||||||
func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
|
|
||||||
return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a structPointer.
|
|
||||||
// In this implementation, a field is identified by its byte offset from the start of the struct.
|
// In this implementation, a field is identified by its byte offset from the start of the struct.
|
||||||
type field uintptr
|
type field uintptr
|
||||||
|
|
||||||
@@ -80,191 +55,254 @@ func toField(f *reflect.StructField) field {
|
|||||||
// invalidField is an invalid field identifier.
|
// invalidField is an invalid field identifier.
|
||||||
const invalidField = ^field(0)
|
const invalidField = ^field(0)
|
||||||
|
|
||||||
|
// zeroField is a noop when calling pointer.offset.
|
||||||
|
const zeroField = field(0)
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
// IsValid reports whether the field identifier is valid.
|
||||||
func (f field) IsValid() bool {
|
func (f field) IsValid() bool {
|
||||||
return f != ^field(0)
|
return f != invalidField
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the address of a []byte field in the struct.
|
// The pointer type below is for the new table-driven encoder/decoder.
|
||||||
func structPointer_Bytes(p structPointer, f field) *[]byte {
|
// The implementation here uses unsafe.Pointer to create a generic pointer.
|
||||||
return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
// In pointer_reflect.go we use reflect instead of unsafe to implement
|
||||||
|
// the same (but slower) interface.
|
||||||
|
type pointer struct {
|
||||||
|
p unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// BytesSlice returns the address of a [][]byte field in the struct.
|
// size of pointer
|
||||||
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
|
var ptrSize = unsafe.Sizeof(uintptr(0))
|
||||||
return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
|
// toPointer converts an interface of pointer type to a pointer
|
||||||
|
// that points to the same target.
|
||||||
|
func toPointer(i *Message) pointer {
|
||||||
|
// Super-tricky - read pointer out of data word of interface value.
|
||||||
|
// Saves ~25ns over the equivalent:
|
||||||
|
// return valToPointer(reflect.ValueOf(*i))
|
||||||
|
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool returns the address of a *bool field in the struct.
|
// toAddrPointer converts an interface to a pointer that points to
|
||||||
func structPointer_Bool(p structPointer, f field) **bool {
|
// the interface data.
|
||||||
return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||||
}
|
// Super-tricky - read or get the address of data word of interface value.
|
||||||
|
if isptr {
|
||||||
// BoolVal returns the address of a bool field in the struct.
|
// The interface is of pointer type, thus it is a direct interface.
|
||||||
func structPointer_BoolVal(p structPointer, f field) *bool {
|
// The data word is the pointer data itself. We take its address.
|
||||||
return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
||||||
}
|
|
||||||
|
|
||||||
// BoolSlice returns the address of a []bool field in the struct.
|
|
||||||
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
|
|
||||||
return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the address of a *string field in the struct.
|
|
||||||
func structPointer_String(p structPointer, f field) **string {
|
|
||||||
return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringVal returns the address of a string field in the struct.
|
|
||||||
func structPointer_StringVal(p structPointer, f field) *string {
|
|
||||||
return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice returns the address of a []string field in the struct.
|
|
||||||
func structPointer_StringSlice(p structPointer, f field) *[]string {
|
|
||||||
return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtMap returns the address of an extension map field in the struct.
|
|
||||||
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
|
|
||||||
return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
|
|
||||||
return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAt returns the reflect.Value for a pointer to a field in the struct.
|
|
||||||
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
|
|
||||||
return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetStructPointer writes a *struct field in the struct.
|
|
||||||
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
|
|
||||||
*(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStructPointer reads a *struct field in the struct.
|
|
||||||
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
|
|
||||||
return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// StructPointerSlice the address of a []*struct field in the struct.
|
|
||||||
func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
|
|
||||||
return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
|
|
||||||
type structPointerSlice []structPointer
|
|
||||||
|
|
||||||
func (v *structPointerSlice) Len() int { return len(*v) }
|
|
||||||
func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
|
|
||||||
func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
|
|
||||||
|
|
||||||
// A word32 is the address of a "pointer to 32-bit value" field.
|
|
||||||
type word32 **uint32
|
|
||||||
|
|
||||||
// IsNil reports whether *v is nil.
|
|
||||||
func word32_IsNil(p word32) bool {
|
|
||||||
return *p == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets *v to point at a newly allocated word set to x.
|
|
||||||
func word32_Set(p word32, o *Buffer, x uint32) {
|
|
||||||
if len(o.uint32s) == 0 {
|
|
||||||
o.uint32s = make([]uint32, uint32PoolSize)
|
|
||||||
}
|
}
|
||||||
o.uint32s[0] = x
|
// The interface is not of pointer type. The data word is the pointer
|
||||||
*p = &o.uint32s[0]
|
// to the data.
|
||||||
o.uint32s = o.uint32s[1:]
|
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets the value pointed at by *v.
|
// valToPointer converts v to a pointer. v must be of pointer type.
|
||||||
func word32_Get(p word32) uint32 {
|
func valToPointer(v reflect.Value) pointer {
|
||||||
return **p
|
return pointer{p: unsafe.Pointer(v.Pointer())}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
|
// offset converts from a pointer to a structure to a pointer to
|
||||||
func structPointer_Word32(p structPointer, f field) word32 {
|
// one of its fields.
|
||||||
return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
|
func (p pointer) offset(f field) pointer {
|
||||||
|
// For safety, we should panic if !f.IsValid, however calling panic causes
|
||||||
|
// this to no longer be inlineable, which is a serious performance cost.
|
||||||
|
/*
|
||||||
|
if !f.IsValid() {
|
||||||
|
panic("invalid field")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A word32Val is the address of a 32-bit value field.
|
func (p pointer) isNil() bool {
|
||||||
type word32Val *uint32
|
return p.p == nil
|
||||||
|
|
||||||
// Set sets *p to x.
|
|
||||||
func word32Val_Set(p word32Val, x uint32) {
|
|
||||||
*p = x
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets the value pointed at by p.
|
func (p pointer) toInt64() *int64 {
|
||||||
func word32Val_Get(p word32Val) uint32 {
|
return (*int64)(p.p)
|
||||||
return *p
|
}
|
||||||
|
func (p pointer) toInt64Ptr() **int64 {
|
||||||
|
return (**int64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toInt64Slice() *[]int64 {
|
||||||
|
return (*[]int64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toInt32() *int32 {
|
||||||
|
return (*int32)(p.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
|
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
|
||||||
func structPointer_Word32Val(p structPointer, f field) word32Val {
|
/*
|
||||||
return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
|
func (p pointer) toInt32Ptr() **int32 {
|
||||||
}
|
return (**int32)(p.p)
|
||||||
|
|
||||||
// A word32Slice is a slice of 32-bit values.
|
|
||||||
type word32Slice []uint32
|
|
||||||
|
|
||||||
func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
|
|
||||||
func (v *word32Slice) Len() int { return len(*v) }
|
|
||||||
func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
|
|
||||||
|
|
||||||
// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
|
|
||||||
func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
|
|
||||||
return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// word64 is like word32 but for 64-bit values.
|
|
||||||
type word64 **uint64
|
|
||||||
|
|
||||||
func word64_Set(p word64, o *Buffer, x uint64) {
|
|
||||||
if len(o.uint64s) == 0 {
|
|
||||||
o.uint64s = make([]uint64, uint64PoolSize)
|
|
||||||
}
|
}
|
||||||
o.uint64s[0] = x
|
func (p pointer) toInt32Slice() *[]int32 {
|
||||||
*p = &o.uint64s[0]
|
return (*[]int32)(p.p)
|
||||||
o.uint64s = o.uint64s[1:]
|
}
|
||||||
|
*/
|
||||||
|
func (p pointer) getInt32Ptr() *int32 {
|
||||||
|
return *(**int32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) setInt32Ptr(v int32) {
|
||||||
|
*(**int32)(p.p) = &v
|
||||||
}
|
}
|
||||||
|
|
||||||
func word64_IsNil(p word64) bool {
|
// getInt32Slice loads a []int32 from p.
|
||||||
return *p == nil
|
// The value returned is aliased with the original slice.
|
||||||
|
// This behavior differs from the implementation in pointer_reflect.go.
|
||||||
|
func (p pointer) getInt32Slice() []int32 {
|
||||||
|
return *(*[]int32)(p.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func word64_Get(p word64) uint64 {
|
// setInt32Slice stores a []int32 to p.
|
||||||
return **p
|
// The value set is aliased with the input slice.
|
||||||
|
// This behavior differs from the implementation in pointer_reflect.go.
|
||||||
|
func (p pointer) setInt32Slice(v []int32) {
|
||||||
|
*(*[]int32)(p.p) = v
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Word64(p structPointer, f field) word64 {
|
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
|
||||||
return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
|
func (p pointer) appendInt32Slice(v int32) {
|
||||||
|
s := (*[]int32)(p.p)
|
||||||
|
*s = append(*s, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// word64Val is like word32Val but for 64-bit values.
|
func (p pointer) toUint64() *uint64 {
|
||||||
type word64Val *uint64
|
return (*uint64)(p.p)
|
||||||
|
}
|
||||||
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
|
func (p pointer) toUint64Ptr() **uint64 {
|
||||||
*p = x
|
return (**uint64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint64Slice() *[]uint64 {
|
||||||
|
return (*[]uint64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32() *uint32 {
|
||||||
|
return (*uint32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32Ptr() **uint32 {
|
||||||
|
return (**uint32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toUint32Slice() *[]uint32 {
|
||||||
|
return (*[]uint32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toBool() *bool {
|
||||||
|
return (*bool)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toBoolPtr() **bool {
|
||||||
|
return (**bool)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toBoolSlice() *[]bool {
|
||||||
|
return (*[]bool)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64() *float64 {
|
||||||
|
return (*float64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64Ptr() **float64 {
|
||||||
|
return (**float64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat64Slice() *[]float64 {
|
||||||
|
return (*[]float64)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32() *float32 {
|
||||||
|
return (*float32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32Ptr() **float32 {
|
||||||
|
return (**float32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toFloat32Slice() *[]float32 {
|
||||||
|
return (*[]float32)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toString() *string {
|
||||||
|
return (*string)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toStringPtr() **string {
|
||||||
|
return (**string)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toStringSlice() *[]string {
|
||||||
|
return (*[]string)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toBytes() *[]byte {
|
||||||
|
return (*[]byte)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toBytesSlice() *[][]byte {
|
||||||
|
return (*[][]byte)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
||||||
|
return (*XXX_InternalExtensions)(p.p)
|
||||||
|
}
|
||||||
|
func (p pointer) toOldExtensions() *map[int32]Extension {
|
||||||
|
return (*map[int32]Extension)(p.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func word64Val_Get(p word64Val) uint64 {
|
// getPointerSlice loads []*T from p as a []pointer.
|
||||||
return *p
|
// The value returned is aliased with the original slice.
|
||||||
|
// This behavior differs from the implementation in pointer_reflect.go.
|
||||||
|
func (p pointer) getPointerSlice() []pointer {
|
||||||
|
// Super-tricky - p should point to a []*T where T is a
|
||||||
|
// message type. We load it as []pointer.
|
||||||
|
return *(*[]pointer)(p.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Word64Val(p structPointer, f field) word64Val {
|
// setPointerSlice stores []pointer into p as a []*T.
|
||||||
return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
|
// The value set is aliased with the input slice.
|
||||||
|
// This behavior differs from the implementation in pointer_reflect.go.
|
||||||
|
func (p pointer) setPointerSlice(v []pointer) {
|
||||||
|
// Super-tricky - p should point to a []*T where T is a
|
||||||
|
// message type. We store it as []pointer.
|
||||||
|
*(*[]pointer)(p.p) = v
|
||||||
}
|
}
|
||||||
|
|
||||||
// word64Slice is like word32Slice but for 64-bit values.
|
// getPointer loads the pointer at p and returns it.
|
||||||
type word64Slice []uint64
|
func (p pointer) getPointer() pointer {
|
||||||
|
return pointer{p: *(*unsafe.Pointer)(p.p)}
|
||||||
func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
|
}
|
||||||
func (v *word64Slice) Len() int { return len(*v) }
|
|
||||||
func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
|
// setPointer stores the pointer q at p.
|
||||||
|
func (p pointer) setPointer(q pointer) {
|
||||||
func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
|
*(*unsafe.Pointer)(p.p) = q.p
|
||||||
return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
|
}
|
||||||
|
|
||||||
|
// append q to the slice pointed to by p.
|
||||||
|
func (p pointer) appendPointer(q pointer) {
|
||||||
|
s := (*[]unsafe.Pointer)(p.p)
|
||||||
|
*s = append(*s, q.p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInterfacePointer returns a pointer that points to the
|
||||||
|
// interface data of the interface pointed by p.
|
||||||
|
func (p pointer) getInterfacePointer() pointer {
|
||||||
|
// Super-tricky - read pointer out of data word of interface value.
|
||||||
|
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
|
||||||
|
}
|
||||||
|
|
||||||
|
// asPointerTo returns a reflect.Value that is a pointer to an
|
||||||
|
// object of type t stored at p.
|
||||||
|
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
||||||
|
return reflect.NewAt(t, p.p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
||||||
|
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
||||||
|
}
|
||||||
|
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
||||||
|
}
|
||||||
|
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
||||||
|
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
||||||
|
}
|
||||||
|
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
||||||
|
}
|
||||||
|
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
||||||
|
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
||||||
|
}
|
||||||
|
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
||||||
|
}
|
||||||
|
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
||||||
|
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
||||||
|
}
|
||||||
|
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
||||||
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-375
@@ -58,42 +58,6 @@ const (
|
|||||||
WireFixed32 = 5
|
WireFixed32 = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
const startSize = 10 // initial slice/string sizes
|
|
||||||
|
|
||||||
// Encoders are defined in encode.go
|
|
||||||
// An encoder outputs the full representation of a field, including its
|
|
||||||
// tag and encoder type.
|
|
||||||
type encoder func(p *Buffer, prop *Properties, base structPointer) error
|
|
||||||
|
|
||||||
// A valueEncoder encodes a single integer in a particular encoding.
|
|
||||||
type valueEncoder func(o *Buffer, x uint64) error
|
|
||||||
|
|
||||||
// Sizers are defined in encode.go
|
|
||||||
// A sizer returns the encoded size of a field, including its tag and encoder
|
|
||||||
// type.
|
|
||||||
type sizer func(prop *Properties, base structPointer) int
|
|
||||||
|
|
||||||
// A valueSizer returns the encoded size of a single integer in a particular
|
|
||||||
// encoding.
|
|
||||||
type valueSizer func(x uint64) int
|
|
||||||
|
|
||||||
// Decoders are defined in decode.go
|
|
||||||
// A decoder creates a value from its wire representation.
|
|
||||||
// Unrecognized subelements are saved in unrec.
|
|
||||||
type decoder func(p *Buffer, prop *Properties, base structPointer) error
|
|
||||||
|
|
||||||
// A valueDecoder decodes a single integer in a particular encoding.
|
|
||||||
type valueDecoder func(o *Buffer) (x uint64, err error)
|
|
||||||
|
|
||||||
// A oneofMarshaler does the marshaling for all oneof fields in a message.
|
|
||||||
type oneofMarshaler func(Message, *Buffer) error
|
|
||||||
|
|
||||||
// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
|
|
||||||
type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
|
|
||||||
|
|
||||||
// A oneofSizer does the sizing for all oneof fields in a message.
|
|
||||||
type oneofSizer func(Message) int
|
|
||||||
|
|
||||||
// tagMap is an optimization over map[int]int for typical protocol buffer
|
// tagMap is an optimization over map[int]int for typical protocol buffer
|
||||||
// use-cases. Encoded protocol buffers are often in tag order with small tag
|
// use-cases. Encoded protocol buffers are often in tag order with small tag
|
||||||
// numbers.
|
// numbers.
|
||||||
@@ -140,13 +104,6 @@ type StructProperties struct {
|
|||||||
decoderTags tagMap // map from proto tag to struct field number
|
decoderTags tagMap // map from proto tag to struct field number
|
||||||
decoderOrigNames map[string]int // map from original name to struct field number
|
decoderOrigNames map[string]int // map from original name to struct field number
|
||||||
order []int // list of struct field numbers in tag order
|
order []int // list of struct field numbers in tag order
|
||||||
unrecField field // field id of the XXX_unrecognized []byte field
|
|
||||||
extendable bool // is this an extendable proto
|
|
||||||
|
|
||||||
oneofMarshaler oneofMarshaler
|
|
||||||
oneofUnmarshaler oneofUnmarshaler
|
|
||||||
oneofSizer oneofSizer
|
|
||||||
stype reflect.Type
|
|
||||||
|
|
||||||
// OneofTypes contains information about the oneof fields in this message.
|
// OneofTypes contains information about the oneof fields in this message.
|
||||||
// It is keyed by the original name of a field.
|
// It is keyed by the original name of a field.
|
||||||
@@ -187,36 +144,19 @@ type Properties struct {
|
|||||||
|
|
||||||
Default string // default value
|
Default string // default value
|
||||||
HasDefault bool // whether an explicit default was provided
|
HasDefault bool // whether an explicit default was provided
|
||||||
def_uint64 uint64
|
|
||||||
|
|
||||||
enc encoder
|
stype reflect.Type // set for struct types only
|
||||||
valEnc valueEncoder // set for bool and numeric types only
|
sprop *StructProperties // set for struct types only
|
||||||
field field
|
|
||||||
tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
|
|
||||||
tagbuf [8]byte
|
|
||||||
stype reflect.Type // set for struct types only
|
|
||||||
sprop *StructProperties // set for struct types only
|
|
||||||
isMarshaler bool
|
|
||||||
isUnmarshaler bool
|
|
||||||
|
|
||||||
mtype reflect.Type // set for map types only
|
mtype reflect.Type // set for map types only
|
||||||
mkeyprop *Properties // set for map types only
|
mkeyprop *Properties // set for map types only
|
||||||
mvalprop *Properties // set for map types only
|
mvalprop *Properties // set for map types only
|
||||||
|
|
||||||
size sizer
|
|
||||||
valSize valueSizer // set for bool and numeric types only
|
|
||||||
|
|
||||||
dec decoder
|
|
||||||
valDec valueDecoder // set for bool and numeric types only
|
|
||||||
|
|
||||||
// If this is a packable field, this will be the decoder for the packed version of the field.
|
|
||||||
packedDec decoder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String formats the properties in the protobuf struct field tag style.
|
// String formats the properties in the protobuf struct field tag style.
|
||||||
func (p *Properties) String() string {
|
func (p *Properties) String() string {
|
||||||
s := p.Wire
|
s := p.Wire
|
||||||
s = ","
|
s += ","
|
||||||
s += strconv.Itoa(p.Tag)
|
s += strconv.Itoa(p.Tag)
|
||||||
if p.Required {
|
if p.Required {
|
||||||
s += ",req"
|
s += ",req"
|
||||||
@@ -262,29 +202,14 @@ func (p *Properties) Parse(s string) {
|
|||||||
switch p.Wire {
|
switch p.Wire {
|
||||||
case "varint":
|
case "varint":
|
||||||
p.WireType = WireVarint
|
p.WireType = WireVarint
|
||||||
p.valEnc = (*Buffer).EncodeVarint
|
|
||||||
p.valDec = (*Buffer).DecodeVarint
|
|
||||||
p.valSize = sizeVarint
|
|
||||||
case "fixed32":
|
case "fixed32":
|
||||||
p.WireType = WireFixed32
|
p.WireType = WireFixed32
|
||||||
p.valEnc = (*Buffer).EncodeFixed32
|
|
||||||
p.valDec = (*Buffer).DecodeFixed32
|
|
||||||
p.valSize = sizeFixed32
|
|
||||||
case "fixed64":
|
case "fixed64":
|
||||||
p.WireType = WireFixed64
|
p.WireType = WireFixed64
|
||||||
p.valEnc = (*Buffer).EncodeFixed64
|
|
||||||
p.valDec = (*Buffer).DecodeFixed64
|
|
||||||
p.valSize = sizeFixed64
|
|
||||||
case "zigzag32":
|
case "zigzag32":
|
||||||
p.WireType = WireVarint
|
p.WireType = WireVarint
|
||||||
p.valEnc = (*Buffer).EncodeZigzag32
|
|
||||||
p.valDec = (*Buffer).DecodeZigzag32
|
|
||||||
p.valSize = sizeZigzag32
|
|
||||||
case "zigzag64":
|
case "zigzag64":
|
||||||
p.WireType = WireVarint
|
p.WireType = WireVarint
|
||||||
p.valEnc = (*Buffer).EncodeZigzag64
|
|
||||||
p.valDec = (*Buffer).DecodeZigzag64
|
|
||||||
p.valSize = sizeZigzag64
|
|
||||||
case "bytes", "group":
|
case "bytes", "group":
|
||||||
p.WireType = WireBytes
|
p.WireType = WireBytes
|
||||||
// no numeric converter for non-numeric types
|
// no numeric converter for non-numeric types
|
||||||
@@ -299,6 +224,7 @@ func (p *Properties) Parse(s string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outer:
|
||||||
for i := 2; i < len(fields); i++ {
|
for i := 2; i < len(fields); i++ {
|
||||||
f := fields[i]
|
f := fields[i]
|
||||||
switch {
|
switch {
|
||||||
@@ -326,229 +252,28 @@ func (p *Properties) Parse(s string) {
|
|||||||
if i+1 < len(fields) {
|
if i+1 < len(fields) {
|
||||||
// Commas aren't escaped, and def is always last.
|
// Commas aren't escaped, and def is always last.
|
||||||
p.Default += "," + strings.Join(fields[i+1:], ",")
|
p.Default += "," + strings.Join(fields[i+1:], ",")
|
||||||
break
|
break outer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func logNoSliceEnc(t1, t2 reflect.Type) {
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
|
|
||||||
}
|
|
||||||
|
|
||||||
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
|
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
|
||||||
|
|
||||||
// Initialize the fields for encoding and decoding.
|
// setFieldProps initializes the field properties for submessages and maps.
|
||||||
func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
|
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
|
||||||
p.enc = nil
|
|
||||||
p.dec = nil
|
|
||||||
p.size = nil
|
|
||||||
|
|
||||||
switch t1 := typ; t1.Kind() {
|
switch t1 := typ; t1.Kind() {
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
|
|
||||||
|
|
||||||
// proto3 scalar types
|
|
||||||
|
|
||||||
case reflect.Bool:
|
|
||||||
p.enc = (*Buffer).enc_proto3_bool
|
|
||||||
p.dec = (*Buffer).dec_proto3_bool
|
|
||||||
p.size = size_proto3_bool
|
|
||||||
case reflect.Int32:
|
|
||||||
p.enc = (*Buffer).enc_proto3_int32
|
|
||||||
p.dec = (*Buffer).dec_proto3_int32
|
|
||||||
p.size = size_proto3_int32
|
|
||||||
case reflect.Uint32:
|
|
||||||
p.enc = (*Buffer).enc_proto3_uint32
|
|
||||||
p.dec = (*Buffer).dec_proto3_int32 // can reuse
|
|
||||||
p.size = size_proto3_uint32
|
|
||||||
case reflect.Int64, reflect.Uint64:
|
|
||||||
p.enc = (*Buffer).enc_proto3_int64
|
|
||||||
p.dec = (*Buffer).dec_proto3_int64
|
|
||||||
p.size = size_proto3_int64
|
|
||||||
case reflect.Float32:
|
|
||||||
p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
|
|
||||||
p.dec = (*Buffer).dec_proto3_int32
|
|
||||||
p.size = size_proto3_uint32
|
|
||||||
case reflect.Float64:
|
|
||||||
p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
|
|
||||||
p.dec = (*Buffer).dec_proto3_int64
|
|
||||||
p.size = size_proto3_int64
|
|
||||||
case reflect.String:
|
|
||||||
p.enc = (*Buffer).enc_proto3_string
|
|
||||||
p.dec = (*Buffer).dec_proto3_string
|
|
||||||
p.size = size_proto3_string
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
switch t2 := t1.Elem(); t2.Kind() {
|
if t1.Elem().Kind() == reflect.Struct {
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
|
|
||||||
break
|
|
||||||
case reflect.Bool:
|
|
||||||
p.enc = (*Buffer).enc_bool
|
|
||||||
p.dec = (*Buffer).dec_bool
|
|
||||||
p.size = size_bool
|
|
||||||
case reflect.Int32:
|
|
||||||
p.enc = (*Buffer).enc_int32
|
|
||||||
p.dec = (*Buffer).dec_int32
|
|
||||||
p.size = size_int32
|
|
||||||
case reflect.Uint32:
|
|
||||||
p.enc = (*Buffer).enc_uint32
|
|
||||||
p.dec = (*Buffer).dec_int32 // can reuse
|
|
||||||
p.size = size_uint32
|
|
||||||
case reflect.Int64, reflect.Uint64:
|
|
||||||
p.enc = (*Buffer).enc_int64
|
|
||||||
p.dec = (*Buffer).dec_int64
|
|
||||||
p.size = size_int64
|
|
||||||
case reflect.Float32:
|
|
||||||
p.enc = (*Buffer).enc_uint32 // can just treat them as bits
|
|
||||||
p.dec = (*Buffer).dec_int32
|
|
||||||
p.size = size_uint32
|
|
||||||
case reflect.Float64:
|
|
||||||
p.enc = (*Buffer).enc_int64 // can just treat them as bits
|
|
||||||
p.dec = (*Buffer).dec_int64
|
|
||||||
p.size = size_int64
|
|
||||||
case reflect.String:
|
|
||||||
p.enc = (*Buffer).enc_string
|
|
||||||
p.dec = (*Buffer).dec_string
|
|
||||||
p.size = size_string
|
|
||||||
case reflect.Struct:
|
|
||||||
p.stype = t1.Elem()
|
p.stype = t1.Elem()
|
||||||
p.isMarshaler = isMarshaler(t1)
|
|
||||||
p.isUnmarshaler = isUnmarshaler(t1)
|
|
||||||
if p.Wire == "bytes" {
|
|
||||||
p.enc = (*Buffer).enc_struct_message
|
|
||||||
p.dec = (*Buffer).dec_struct_message
|
|
||||||
p.size = size_struct_message
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_struct_group
|
|
||||||
p.dec = (*Buffer).dec_struct_group
|
|
||||||
p.size = size_struct_group
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
switch t2 := t1.Elem(); t2.Kind() {
|
if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
|
||||||
default:
|
p.stype = t2.Elem()
|
||||||
logNoSliceEnc(t1, t2)
|
|
||||||
break
|
|
||||||
case reflect.Bool:
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_bool
|
|
||||||
p.size = size_slice_packed_bool
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_bool
|
|
||||||
p.size = size_slice_bool
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_bool
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_bool
|
|
||||||
case reflect.Int32:
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_int32
|
|
||||||
p.size = size_slice_packed_int32
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_int32
|
|
||||||
p.size = size_slice_int32
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_int32
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_int32
|
|
||||||
case reflect.Uint32:
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_uint32
|
|
||||||
p.size = size_slice_packed_uint32
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_uint32
|
|
||||||
p.size = size_slice_uint32
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_int32
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_int32
|
|
||||||
case reflect.Int64, reflect.Uint64:
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_int64
|
|
||||||
p.size = size_slice_packed_int64
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_int64
|
|
||||||
p.size = size_slice_int64
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_int64
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_int64
|
|
||||||
case reflect.Uint8:
|
|
||||||
p.dec = (*Buffer).dec_slice_byte
|
|
||||||
if p.proto3 {
|
|
||||||
p.enc = (*Buffer).enc_proto3_slice_byte
|
|
||||||
p.size = size_proto3_slice_byte
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_byte
|
|
||||||
p.size = size_slice_byte
|
|
||||||
}
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
switch t2.Bits() {
|
|
||||||
case 32:
|
|
||||||
// can just treat them as bits
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_uint32
|
|
||||||
p.size = size_slice_packed_uint32
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_uint32
|
|
||||||
p.size = size_slice_uint32
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_int32
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_int32
|
|
||||||
case 64:
|
|
||||||
// can just treat them as bits
|
|
||||||
if p.Packed {
|
|
||||||
p.enc = (*Buffer).enc_slice_packed_int64
|
|
||||||
p.size = size_slice_packed_int64
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_int64
|
|
||||||
p.size = size_slice_int64
|
|
||||||
}
|
|
||||||
p.dec = (*Buffer).dec_slice_int64
|
|
||||||
p.packedDec = (*Buffer).dec_slice_packed_int64
|
|
||||||
default:
|
|
||||||
logNoSliceEnc(t1, t2)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
p.enc = (*Buffer).enc_slice_string
|
|
||||||
p.dec = (*Buffer).dec_slice_string
|
|
||||||
p.size = size_slice_string
|
|
||||||
case reflect.Ptr:
|
|
||||||
switch t3 := t2.Elem(); t3.Kind() {
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
|
|
||||||
break
|
|
||||||
case reflect.Struct:
|
|
||||||
p.stype = t2.Elem()
|
|
||||||
p.isMarshaler = isMarshaler(t2)
|
|
||||||
p.isUnmarshaler = isUnmarshaler(t2)
|
|
||||||
if p.Wire == "bytes" {
|
|
||||||
p.enc = (*Buffer).enc_slice_struct_message
|
|
||||||
p.dec = (*Buffer).dec_slice_struct_message
|
|
||||||
p.size = size_slice_struct_message
|
|
||||||
} else {
|
|
||||||
p.enc = (*Buffer).enc_slice_struct_group
|
|
||||||
p.dec = (*Buffer).dec_slice_struct_group
|
|
||||||
p.size = size_slice_struct_group
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
switch t2.Elem().Kind() {
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
|
|
||||||
break
|
|
||||||
case reflect.Uint8:
|
|
||||||
p.enc = (*Buffer).enc_slice_slice_byte
|
|
||||||
p.dec = (*Buffer).dec_slice_slice_byte
|
|
||||||
p.size = size_slice_slice_byte
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
p.enc = (*Buffer).enc_new_map
|
|
||||||
p.dec = (*Buffer).dec_new_map
|
|
||||||
p.size = size_new_map
|
|
||||||
|
|
||||||
p.mtype = t1
|
p.mtype = t1
|
||||||
p.mkeyprop = &Properties{}
|
p.mkeyprop = &Properties{}
|
||||||
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
||||||
@@ -562,20 +287,6 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
|
|||||||
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// precalculate tag code
|
|
||||||
wire := p.WireType
|
|
||||||
if p.Packed {
|
|
||||||
wire = WireBytes
|
|
||||||
}
|
|
||||||
x := uint32(p.Tag)<<3 | uint32(wire)
|
|
||||||
i := 0
|
|
||||||
for i = 0; x > 127; i++ {
|
|
||||||
p.tagbuf[i] = 0x80 | uint8(x&0x7F)
|
|
||||||
x >>= 7
|
|
||||||
}
|
|
||||||
p.tagbuf[i] = uint8(x)
|
|
||||||
p.tagcode = p.tagbuf[0 : i+1]
|
|
||||||
|
|
||||||
if p.stype != nil {
|
if p.stype != nil {
|
||||||
if lockGetProp {
|
if lockGetProp {
|
||||||
p.sprop = GetProperties(p.stype)
|
p.sprop = GetProperties(p.stype)
|
||||||
@@ -586,32 +297,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||||
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// isMarshaler reports whether type t implements Marshaler.
|
|
||||||
func isMarshaler(t reflect.Type) bool {
|
|
||||||
// We're checking for (likely) pointer-receiver methods
|
|
||||||
// so if t is not a pointer, something is very wrong.
|
|
||||||
// The calls above only invoke isMarshaler on pointer types.
|
|
||||||
if t.Kind() != reflect.Ptr {
|
|
||||||
panic("proto: misuse of isMarshaler")
|
|
||||||
}
|
|
||||||
return t.Implements(marshalerType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isUnmarshaler reports whether type t implements Unmarshaler.
|
|
||||||
func isUnmarshaler(t reflect.Type) bool {
|
|
||||||
// We're checking for (likely) pointer-receiver methods
|
|
||||||
// so if t is not a pointer, something is very wrong.
|
|
||||||
// The calls above only invoke isUnmarshaler on pointer types.
|
|
||||||
if t.Kind() != reflect.Ptr {
|
|
||||||
panic("proto: misuse of isUnmarshaler")
|
|
||||||
}
|
|
||||||
return t.Implements(unmarshalerType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init populates the properties from a protocol buffer struct tag.
|
// Init populates the properties from a protocol buffer struct tag.
|
||||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
||||||
p.init(typ, name, tag, f, true)
|
p.init(typ, name, tag, f, true)
|
||||||
@@ -621,14 +309,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
|
|||||||
// "bytes,49,opt,def=hello!"
|
// "bytes,49,opt,def=hello!"
|
||||||
p.Name = name
|
p.Name = name
|
||||||
p.OrigName = name
|
p.OrigName = name
|
||||||
if f != nil {
|
|
||||||
p.field = toField(f)
|
|
||||||
}
|
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.Parse(tag)
|
p.Parse(tag)
|
||||||
p.setEncAndDec(typ, f, lockGetProp)
|
p.setFieldProps(typ, f, lockGetProp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -678,9 +363,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
propertiesMap[t] = prop
|
propertiesMap[t] = prop
|
||||||
|
|
||||||
// build properties
|
// build properties
|
||||||
prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
|
|
||||||
reflect.PtrTo(t).Implements(extendableProtoV1Type)
|
|
||||||
prop.unrecField = invalidField
|
|
||||||
prop.Prop = make([]*Properties, t.NumField())
|
prop.Prop = make([]*Properties, t.NumField())
|
||||||
prop.order = make([]int, t.NumField())
|
prop.order = make([]int, t.NumField())
|
||||||
|
|
||||||
@@ -690,17 +372,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
name := f.Name
|
name := f.Name
|
||||||
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
||||||
|
|
||||||
if f.Name == "XXX_InternalExtensions" { // special case
|
|
||||||
p.enc = (*Buffer).enc_exts
|
|
||||||
p.dec = nil // not needed
|
|
||||||
p.size = size_exts
|
|
||||||
} else if f.Name == "XXX_extensions" { // special case
|
|
||||||
p.enc = (*Buffer).enc_map
|
|
||||||
p.dec = nil // not needed
|
|
||||||
p.size = size_map
|
|
||||||
} else if f.Name == "XXX_unrecognized" { // special case
|
|
||||||
prop.unrecField = toField(&f)
|
|
||||||
}
|
|
||||||
oneof := f.Tag.Get("protobuf_oneof") // special case
|
oneof := f.Tag.Get("protobuf_oneof") // special case
|
||||||
if oneof != "" {
|
if oneof != "" {
|
||||||
// Oneof fields don't use the traditional protobuf tag.
|
// Oneof fields don't use the traditional protobuf tag.
|
||||||
@@ -715,9 +386,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
}
|
}
|
||||||
print("\n")
|
print("\n")
|
||||||
}
|
}
|
||||||
if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-order prop.order.
|
// Re-order prop.order.
|
||||||
@@ -728,8 +396,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
}
|
}
|
||||||
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
||||||
var oots []interface{}
|
var oots []interface{}
|
||||||
prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
|
_, _, _, oots = om.XXX_OneofFuncs()
|
||||||
prop.stype = t
|
|
||||||
|
|
||||||
// Interpret oneof metadata.
|
// Interpret oneof metadata.
|
||||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||||
@@ -779,30 +446,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
return prop
|
return prop
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the Properties object for the x[0]'th field of the structure.
|
|
||||||
func propByIndex(t reflect.Type, x []int) *Properties {
|
|
||||||
if len(x) != 1 {
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
prop := GetProperties(t)
|
|
||||||
return prop.Prop[x[0]]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the address and type of a pointer to a struct from an interface.
|
|
||||||
func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
|
|
||||||
if pb == nil {
|
|
||||||
err = ErrNil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// get the reflect type of the pointer to the struct.
|
|
||||||
t = reflect.TypeOf(pb)
|
|
||||||
// get the address of the struct.
|
|
||||||
value := reflect.ValueOf(pb)
|
|
||||||
b = toStructPointer(value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// A global registry of enum types.
|
// A global registry of enum types.
|
||||||
// The generated code will register the generated maps by calling RegisterEnum.
|
// The generated code will register the generated maps by calling RegisterEnum.
|
||||||
|
|
||||||
@@ -826,20 +469,42 @@ func EnumValueMap(enumType string) map[string]int32 {
|
|||||||
// A registry of all linked message types.
|
// A registry of all linked message types.
|
||||||
// The string is a fully-qualified proto name ("pkg.Message").
|
// The string is a fully-qualified proto name ("pkg.Message").
|
||||||
var (
|
var (
|
||||||
protoTypes = make(map[string]reflect.Type)
|
protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
|
||||||
revProtoTypes = make(map[reflect.Type]string)
|
protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
|
||||||
|
revProtoTypes = make(map[reflect.Type]string)
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterType is called from generated code and maps from the fully qualified
|
// RegisterType is called from generated code and maps from the fully qualified
|
||||||
// proto name to the type (pointer to struct) of the protocol buffer.
|
// proto name to the type (pointer to struct) of the protocol buffer.
|
||||||
func RegisterType(x Message, name string) {
|
func RegisterType(x Message, name string) {
|
||||||
if _, ok := protoTypes[name]; ok {
|
if _, ok := protoTypedNils[name]; ok {
|
||||||
// TODO: Some day, make this a panic.
|
// TODO: Some day, make this a panic.
|
||||||
log.Printf("proto: duplicate proto type registered: %s", name)
|
log.Printf("proto: duplicate proto type registered: %s", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t := reflect.TypeOf(x)
|
t := reflect.TypeOf(x)
|
||||||
protoTypes[name] = t
|
if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
|
||||||
|
// Generated code always calls RegisterType with nil x.
|
||||||
|
// This check is just for extra safety.
|
||||||
|
protoTypedNils[name] = x
|
||||||
|
} else {
|
||||||
|
protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
|
||||||
|
}
|
||||||
|
revProtoTypes[t] = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterMapType is called from generated code and maps from the fully qualified
|
||||||
|
// proto name to the native map type of the proto map definition.
|
||||||
|
func RegisterMapType(x interface{}, name string) {
|
||||||
|
if reflect.TypeOf(x).Kind() != reflect.Map {
|
||||||
|
panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
|
||||||
|
}
|
||||||
|
if _, ok := protoMapTypes[name]; ok {
|
||||||
|
log.Printf("proto: duplicate proto type registered: %s", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t := reflect.TypeOf(x)
|
||||||
|
protoMapTypes[name] = t
|
||||||
revProtoTypes[t] = name
|
revProtoTypes[t] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,7 +520,14 @@ func MessageName(x Message) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MessageType returns the message type (pointer to struct) for a named message.
|
// MessageType returns the message type (pointer to struct) for a named message.
|
||||||
func MessageType(name string) reflect.Type { return protoTypes[name] }
|
// The type is not guaranteed to implement proto.Message if the name refers to a
|
||||||
|
// map entry.
|
||||||
|
func MessageType(name string) reflect.Type {
|
||||||
|
if t, ok := protoTypedNils[name]; ok {
|
||||||
|
return reflect.TypeOf(t)
|
||||||
|
}
|
||||||
|
return protoMapTypes[name]
|
||||||
|
}
|
||||||
|
|
||||||
// A registry of all linked proto files.
|
// A registry of all linked proto files.
|
||||||
var (
|
var (
|
||||||
|
|||||||
+2681
File diff suppressed because it is too large
Load Diff
+654
@@ -0,0 +1,654 @@
|
|||||||
|
// Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
//
|
||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// https://github.com/golang/protobuf
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Merge merges the src message into dst.
|
||||||
|
// This assumes that dst and src of the same type and are non-nil.
|
||||||
|
func (a *InternalMessageInfo) Merge(dst, src Message) {
|
||||||
|
mi := atomicLoadMergeInfo(&a.merge)
|
||||||
|
if mi == nil {
|
||||||
|
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
|
||||||
|
atomicStoreMergeInfo(&a.merge, mi)
|
||||||
|
}
|
||||||
|
mi.merge(toPointer(&dst), toPointer(&src))
|
||||||
|
}
|
||||||
|
|
||||||
|
type mergeInfo struct {
|
||||||
|
typ reflect.Type
|
||||||
|
|
||||||
|
initialized int32 // 0: only typ is valid, 1: everything is valid
|
||||||
|
lock sync.Mutex
|
||||||
|
|
||||||
|
fields []mergeFieldInfo
|
||||||
|
unrecognized field // Offset of XXX_unrecognized
|
||||||
|
}
|
||||||
|
|
||||||
|
type mergeFieldInfo struct {
|
||||||
|
field field // Offset of field, guaranteed to be valid
|
||||||
|
|
||||||
|
// isPointer reports whether the value in the field is a pointer.
|
||||||
|
// This is true for the following situations:
|
||||||
|
// * Pointer to struct
|
||||||
|
// * Pointer to basic type (proto2 only)
|
||||||
|
// * Slice (first value in slice header is a pointer)
|
||||||
|
// * String (first value in string header is a pointer)
|
||||||
|
isPointer bool
|
||||||
|
|
||||||
|
// basicWidth reports the width of the field assuming that it is directly
|
||||||
|
// embedded in the struct (as is the case for basic types in proto3).
|
||||||
|
// The possible values are:
|
||||||
|
// 0: invalid
|
||||||
|
// 1: bool
|
||||||
|
// 4: int32, uint32, float32
|
||||||
|
// 8: int64, uint64, float64
|
||||||
|
basicWidth int
|
||||||
|
|
||||||
|
// Where dst and src are pointers to the types being merged.
|
||||||
|
merge func(dst, src pointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
mergeInfoMap = map[reflect.Type]*mergeInfo{}
|
||||||
|
mergeInfoLock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func getMergeInfo(t reflect.Type) *mergeInfo {
|
||||||
|
mergeInfoLock.Lock()
|
||||||
|
defer mergeInfoLock.Unlock()
|
||||||
|
mi := mergeInfoMap[t]
|
||||||
|
if mi == nil {
|
||||||
|
mi = &mergeInfo{typ: t}
|
||||||
|
mergeInfoMap[t] = mi
|
||||||
|
}
|
||||||
|
return mi
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge merges src into dst assuming they are both of type *mi.typ.
|
||||||
|
func (mi *mergeInfo) merge(dst, src pointer) {
|
||||||
|
if dst.isNil() {
|
||||||
|
panic("proto: nil destination")
|
||||||
|
}
|
||||||
|
if src.isNil() {
|
||||||
|
return // Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
if atomic.LoadInt32(&mi.initialized) == 0 {
|
||||||
|
mi.computeMergeInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fi := range mi.fields {
|
||||||
|
sfp := src.offset(fi.field)
|
||||||
|
|
||||||
|
// As an optimization, we can avoid the merge function call cost
|
||||||
|
// if we know for sure that the source will have no effect
|
||||||
|
// by checking if it is the zero value.
|
||||||
|
if unsafeAllowed {
|
||||||
|
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fi.basicWidth > 0 {
|
||||||
|
switch {
|
||||||
|
case fi.basicWidth == 1 && !*sfp.toBool():
|
||||||
|
continue
|
||||||
|
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
|
||||||
|
continue
|
||||||
|
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dfp := dst.offset(fi.field)
|
||||||
|
fi.merge(dfp, sfp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make this faster?
|
||||||
|
out := dst.asPointerTo(mi.typ).Elem()
|
||||||
|
in := src.asPointerTo(mi.typ).Elem()
|
||||||
|
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
||||||
|
emOut, _ := extendable(out.Addr().Interface())
|
||||||
|
mIn, muIn := emIn.extensionsRead()
|
||||||
|
if mIn != nil {
|
||||||
|
mOut := emOut.extensionsWrite()
|
||||||
|
muIn.Lock()
|
||||||
|
mergeExtension(mOut, mIn)
|
||||||
|
muIn.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mi.unrecognized.IsValid() {
|
||||||
|
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
|
||||||
|
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mi *mergeInfo) computeMergeInfo() {
|
||||||
|
mi.lock.Lock()
|
||||||
|
defer mi.lock.Unlock()
|
||||||
|
if mi.initialized != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t := mi.typ
|
||||||
|
n := t.NumField()
|
||||||
|
|
||||||
|
props := GetProperties(t)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if strings.HasPrefix(f.Name, "XXX_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mfi := mergeFieldInfo{field: toField(&f)}
|
||||||
|
tf := f.Type
|
||||||
|
|
||||||
|
// As an optimization, we can avoid the merge function call cost
|
||||||
|
// if we know for sure that the source will have no effect
|
||||||
|
// by checking if it is the zero value.
|
||||||
|
if unsafeAllowed {
|
||||||
|
switch tf.Kind() {
|
||||||
|
case reflect.Ptr, reflect.Slice, reflect.String:
|
||||||
|
// As a special case, we assume slices and strings are pointers
|
||||||
|
// since we know that the first field in the SliceSlice or
|
||||||
|
// StringHeader is a data pointer.
|
||||||
|
mfi.isPointer = true
|
||||||
|
case reflect.Bool:
|
||||||
|
mfi.basicWidth = 1
|
||||||
|
case reflect.Int32, reflect.Uint32, reflect.Float32:
|
||||||
|
mfi.basicWidth = 4
|
||||||
|
case reflect.Int64, reflect.Uint64, reflect.Float64:
|
||||||
|
mfi.basicWidth = 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap tf to get at its most basic type.
|
||||||
|
var isPointer, isSlice bool
|
||||||
|
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
||||||
|
isSlice = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if tf.Kind() == reflect.Ptr {
|
||||||
|
isPointer = true
|
||||||
|
tf = tf.Elem()
|
||||||
|
}
|
||||||
|
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
||||||
|
panic("both pointer and slice for basic type in " + tf.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tf.Kind() {
|
||||||
|
case reflect.Int32:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []int32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
|
||||||
|
/*
|
||||||
|
sfsp := src.toInt32Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toInt32Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []int64{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
sfs := src.getInt32Slice()
|
||||||
|
if sfs != nil {
|
||||||
|
dfs := dst.getInt32Slice()
|
||||||
|
dfs = append(dfs, sfs...)
|
||||||
|
if dfs == nil {
|
||||||
|
dfs = []int32{}
|
||||||
|
}
|
||||||
|
dst.setInt32Slice(dfs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *int32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
|
||||||
|
/*
|
||||||
|
sfpp := src.toInt32Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toInt32Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Int32(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
sfp := src.getInt32Ptr()
|
||||||
|
if sfp != nil {
|
||||||
|
dfp := dst.getInt32Ptr()
|
||||||
|
if dfp == nil {
|
||||||
|
dst.setInt32Ptr(*sfp)
|
||||||
|
} else {
|
||||||
|
*dfp = *sfp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., int32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toInt32(); v != 0 {
|
||||||
|
*dst.toInt32() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []int64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toInt64Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toInt64Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []int64{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *int64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toInt64Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toInt64Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Int64(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., int64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toInt64(); v != 0 {
|
||||||
|
*dst.toInt64() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint32:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []uint32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toUint32Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toUint32Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []uint32{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *uint32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toUint32Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toUint32Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Uint32(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., uint32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toUint32(); v != 0 {
|
||||||
|
*dst.toUint32() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []uint64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toUint64Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toUint64Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []uint64{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *uint64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toUint64Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toUint64Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Uint64(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., uint64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toUint64(); v != 0 {
|
||||||
|
*dst.toUint64() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Float32:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []float32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toFloat32Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toFloat32Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []float32{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *float32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toFloat32Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toFloat32Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Float32(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., float32
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toFloat32(); v != 0 {
|
||||||
|
*dst.toFloat32() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Float64:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []float64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toFloat64Slice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toFloat64Slice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []float64{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *float64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toFloat64Ptr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toFloat64Ptr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Float64(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., float64
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toFloat64(); v != 0 {
|
||||||
|
*dst.toFloat64() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Bool:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []bool
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toBoolSlice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toBoolSlice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []bool{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *bool
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toBoolPtr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toBoolPtr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = Bool(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., bool
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toBool(); v {
|
||||||
|
*dst.toBool() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
switch {
|
||||||
|
case isSlice: // E.g., []string
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfsp := src.toStringSlice()
|
||||||
|
if *sfsp != nil {
|
||||||
|
dfsp := dst.toStringSlice()
|
||||||
|
*dfsp = append(*dfsp, *sfsp...)
|
||||||
|
if *dfsp == nil {
|
||||||
|
*dfsp = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isPointer: // E.g., *string
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sfpp := src.toStringPtr()
|
||||||
|
if *sfpp != nil {
|
||||||
|
dfpp := dst.toStringPtr()
|
||||||
|
if *dfpp == nil {
|
||||||
|
*dfpp = String(**sfpp)
|
||||||
|
} else {
|
||||||
|
**dfpp = **sfpp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., string
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
if v := *src.toString(); v != "" {
|
||||||
|
*dst.toString() = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
isProto3 := props.Prop[i].proto3
|
||||||
|
switch {
|
||||||
|
case isPointer:
|
||||||
|
panic("bad pointer in byte slice case in " + tf.Name())
|
||||||
|
case tf.Elem().Kind() != reflect.Uint8:
|
||||||
|
panic("bad element kind in byte slice case in " + tf.Name())
|
||||||
|
case isSlice: // E.g., [][]byte
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sbsp := src.toBytesSlice()
|
||||||
|
if *sbsp != nil {
|
||||||
|
dbsp := dst.toBytesSlice()
|
||||||
|
for _, sb := range *sbsp {
|
||||||
|
if sb == nil {
|
||||||
|
*dbsp = append(*dbsp, nil)
|
||||||
|
} else {
|
||||||
|
*dbsp = append(*dbsp, append([]byte{}, sb...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if *dbsp == nil {
|
||||||
|
*dbsp = [][]byte{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., []byte
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sbp := src.toBytes()
|
||||||
|
if *sbp != nil {
|
||||||
|
dbp := dst.toBytes()
|
||||||
|
if !isProto3 || len(*sbp) > 0 {
|
||||||
|
*dbp = append([]byte{}, *sbp...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
switch {
|
||||||
|
case !isPointer:
|
||||||
|
panic(fmt.Sprintf("message field %s without pointer", tf))
|
||||||
|
case isSlice: // E.g., []*pb.T
|
||||||
|
mi := getMergeInfo(tf)
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sps := src.getPointerSlice()
|
||||||
|
if sps != nil {
|
||||||
|
dps := dst.getPointerSlice()
|
||||||
|
for _, sp := range sps {
|
||||||
|
var dp pointer
|
||||||
|
if !sp.isNil() {
|
||||||
|
dp = valToPointer(reflect.New(tf))
|
||||||
|
mi.merge(dp, sp)
|
||||||
|
}
|
||||||
|
dps = append(dps, dp)
|
||||||
|
}
|
||||||
|
if dps == nil {
|
||||||
|
dps = []pointer{}
|
||||||
|
}
|
||||||
|
dst.setPointerSlice(dps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // E.g., *pb.T
|
||||||
|
mi := getMergeInfo(tf)
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sp := src.getPointer()
|
||||||
|
if !sp.isNil() {
|
||||||
|
dp := dst.getPointer()
|
||||||
|
if dp.isNil() {
|
||||||
|
dp = valToPointer(reflect.New(tf))
|
||||||
|
dst.setPointer(dp)
|
||||||
|
}
|
||||||
|
mi.merge(dp, sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic("bad pointer or slice in map case in " + tf.Name())
|
||||||
|
default: // E.g., map[K]V
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
sm := src.asPointerTo(tf).Elem()
|
||||||
|
if sm.Len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dm := dst.asPointerTo(tf).Elem()
|
||||||
|
if dm.IsNil() {
|
||||||
|
dm.Set(reflect.MakeMap(tf))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tf.Elem().Kind() {
|
||||||
|
case reflect.Ptr: // Proto struct (e.g., *T)
|
||||||
|
for _, key := range sm.MapKeys() {
|
||||||
|
val := sm.MapIndex(key)
|
||||||
|
val = reflect.ValueOf(Clone(val.Interface().(Message)))
|
||||||
|
dm.SetMapIndex(key, val)
|
||||||
|
}
|
||||||
|
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
||||||
|
for _, key := range sm.MapKeys() {
|
||||||
|
val := sm.MapIndex(key)
|
||||||
|
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
|
||||||
|
dm.SetMapIndex(key, val)
|
||||||
|
}
|
||||||
|
default: // Basic type (e.g., string)
|
||||||
|
for _, key := range sm.MapKeys() {
|
||||||
|
val := sm.MapIndex(key)
|
||||||
|
dm.SetMapIndex(key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
// Must be oneof field.
|
||||||
|
switch {
|
||||||
|
case isPointer || isSlice:
|
||||||
|
panic("bad pointer or slice in interface case in " + tf.Name())
|
||||||
|
default: // E.g., interface{}
|
||||||
|
// TODO: Make this faster?
|
||||||
|
mfi.merge = func(dst, src pointer) {
|
||||||
|
su := src.asPointerTo(tf).Elem()
|
||||||
|
if !su.IsNil() {
|
||||||
|
du := dst.asPointerTo(tf).Elem()
|
||||||
|
typ := su.Elem().Type()
|
||||||
|
if du.IsNil() || du.Elem().Type() != typ {
|
||||||
|
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
|
||||||
|
}
|
||||||
|
sv := su.Elem().Elem().Field(0)
|
||||||
|
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dv := du.Elem().Elem().Field(0)
|
||||||
|
if dv.Kind() == reflect.Ptr && dv.IsNil() {
|
||||||
|
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
|
||||||
|
}
|
||||||
|
switch sv.Type().Kind() {
|
||||||
|
case reflect.Ptr: // Proto struct (e.g., *T)
|
||||||
|
Merge(dv.Interface().(Message), sv.Interface().(Message))
|
||||||
|
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
||||||
|
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
|
||||||
|
default: // Basic type (e.g., string)
|
||||||
|
dv.Set(sv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("merger not found for type:%s", tf))
|
||||||
|
}
|
||||||
|
mi.fields = append(mi.fields, mfi)
|
||||||
|
}
|
||||||
|
|
||||||
|
mi.unrecognized = invalidField
|
||||||
|
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
|
||||||
|
if f.Type != reflect.TypeOf([]byte{}) {
|
||||||
|
panic("expected XXX_unrecognized to be of type []byte")
|
||||||
|
}
|
||||||
|
mi.unrecognized = toField(&f)
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StoreInt32(&mi.initialized, 1)
|
||||||
|
}
|
||||||
+1967
File diff suppressed because it is too large
Load Diff
+25
-36
@@ -50,7 +50,6 @@ import (
|
|||||||
var (
|
var (
|
||||||
newline = []byte("\n")
|
newline = []byte("\n")
|
||||||
spaces = []byte(" ")
|
spaces = []byte(" ")
|
||||||
gtNewline = []byte(">\n")
|
|
||||||
endBraceNewline = []byte("}\n")
|
endBraceNewline = []byte("}\n")
|
||||||
backslashN = []byte{'\\', 'n'}
|
backslashN = []byte{'\\', 'n'}
|
||||||
backslashR = []byte{'\\', 'r'}
|
backslashR = []byte{'\\', 'r'}
|
||||||
@@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// raw is the interface satisfied by RawMessage.
|
|
||||||
type raw interface {
|
|
||||||
Bytes() []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func requiresQuotes(u string) bool {
|
func requiresQuotes(u string) bool {
|
||||||
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
||||||
for _, ch := range u {
|
for _, ch := range u {
|
||||||
@@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||||||
props := sprops.Prop[i]
|
props := sprops.Prop[i]
|
||||||
name := st.Field(i).Name
|
name := st.Field(i).Name
|
||||||
|
|
||||||
|
if name == "XXX_NoUnkeyedLiteral" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(name, "XXX_") {
|
if strings.HasPrefix(name, "XXX_") {
|
||||||
// There are two XXX_ fields:
|
// There are two XXX_ fields:
|
||||||
// XXX_unrecognized []byte
|
// XXX_unrecognized []byte
|
||||||
@@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if b, ok := fv.Interface().(raw); ok {
|
|
||||||
if err := writeRaw(w, b.Bytes()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enums have a String method, so writeAny will work fine.
|
// Enums have a String method, so writeAny will work fine.
|
||||||
if err := tm.writeAny(w, fv, props); err != nil {
|
if err := tm.writeAny(w, fv, props); err != nil {
|
||||||
@@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||||||
|
|
||||||
// Extensions (the XXX_extensions field).
|
// Extensions (the XXX_extensions field).
|
||||||
pv := sv.Addr()
|
pv := sv.Addr()
|
||||||
if _, ok := extendable(pv.Interface()); ok {
|
if _, err := extendable(pv.Interface()); err == nil {
|
||||||
if err := tm.writeExtensions(w, pv); err != nil {
|
if err := tm.writeExtensions(w, pv); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeRaw writes an uninterpreted raw message.
|
|
||||||
func writeRaw(w *textWriter, b []byte) error {
|
|
||||||
if err := w.WriteByte('<'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.indent()
|
|
||||||
if err := writeUnknownStruct(w, b); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.unindent()
|
|
||||||
if err := w.WriteByte('>'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeAny writes an arbitrary field.
|
// writeAny writes an arbitrary field.
|
||||||
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
||||||
v = reflect.Indirect(v)
|
v = reflect.Indirect(v)
|
||||||
@@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.indent()
|
w.indent()
|
||||||
|
if v.CanAddr() {
|
||||||
|
// Calling v.Interface on a struct causes the reflect package to
|
||||||
|
// copy the entire struct. This is racy with the new Marshaler
|
||||||
|
// since we atomically update the XXX_sizecache.
|
||||||
|
//
|
||||||
|
// Thus, we retrieve a pointer to the struct if possible to avoid
|
||||||
|
// a race since v.Interface on the pointer doesn't copy the struct.
|
||||||
|
//
|
||||||
|
// If v is not addressable, then we are not worried about a race
|
||||||
|
// since it implies that the binary Marshaler cannot possibly be
|
||||||
|
// mutating this value.
|
||||||
|
v = v.Addr()
|
||||||
|
}
|
||||||
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
|
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
|
||||||
text, err := etm.MarshalText()
|
text, err := etm.MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
|
|||||||
if _, err = w.Write(text); err != nil {
|
if _, err = w.Write(text); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if err := tm.writeStruct(w, v); err != nil {
|
} else {
|
||||||
return err
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
if err := tm.writeStruct(w, v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
w.unindent()
|
w.unindent()
|
||||||
if err := w.WriteByte(ket); err != nil {
|
if err := w.WriteByte(ket); err != nil {
|
||||||
|
|||||||
+31
-46
@@ -206,7 +206,6 @@ func (p *textParser) advance() {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
errBadUTF8 = errors.New("proto: bad UTF-8")
|
errBadUTF8 = errors.New("proto: bad UTF-8")
|
||||||
errBadHex = errors.New("proto: bad hexadecimal")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func unquoteC(s string, quote rune) (string, error) {
|
func unquoteC(s string, quote rune) (string, error) {
|
||||||
@@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) {
|
|||||||
return "?", s, nil // trigraph workaround
|
return "?", s, nil // trigraph workaround
|
||||||
case '\'', '"', '\\':
|
case '\'', '"', '\\':
|
||||||
return string(r), s, nil
|
return string(r), s, nil
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
if len(s) < 2 {
|
if len(s) < 2 {
|
||||||
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
||||||
}
|
}
|
||||||
base := 8
|
ss := string(r) + s[:2]
|
||||||
ss := s[:2]
|
|
||||||
s = s[2:]
|
s = s[2:]
|
||||||
if r == 'x' || r == 'X' {
|
i, err := strconv.ParseUint(ss, 8, 8)
|
||||||
base = 16
|
|
||||||
} else {
|
|
||||||
ss = string(r) + ss
|
|
||||||
}
|
|
||||||
i, err := strconv.ParseUint(ss, base, 8)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
||||||
}
|
}
|
||||||
return string([]byte{byte(i)}), s, nil
|
return string([]byte{byte(i)}), s, nil
|
||||||
case 'u', 'U':
|
case 'x', 'X', 'u', 'U':
|
||||||
n := 4
|
var n int
|
||||||
if r == 'U' {
|
switch r {
|
||||||
|
case 'x', 'X':
|
||||||
|
n = 2
|
||||||
|
case 'u':
|
||||||
|
n = 4
|
||||||
|
case 'U':
|
||||||
n = 8
|
n = 8
|
||||||
}
|
}
|
||||||
if len(s) < n {
|
if len(s) < n {
|
||||||
return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
|
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
||||||
}
|
|
||||||
|
|
||||||
bs := make([]byte, n/2)
|
|
||||||
for i := 0; i < n; i += 2 {
|
|
||||||
a, ok1 := unhex(s[i])
|
|
||||||
b, ok2 := unhex(s[i+1])
|
|
||||||
if !ok1 || !ok2 {
|
|
||||||
return "", "", errBadHex
|
|
||||||
}
|
|
||||||
bs[i/2] = a<<4 | b
|
|
||||||
}
|
}
|
||||||
|
ss := s[:n]
|
||||||
s = s[n:]
|
s = s[n:]
|
||||||
return string(bs), s, nil
|
i, err := strconv.ParseUint(ss, 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
||||||
|
}
|
||||||
|
if r == 'x' || r == 'X' {
|
||||||
|
return string([]byte{byte(i)}), s, nil
|
||||||
|
}
|
||||||
|
if i > utf8.MaxRune {
|
||||||
|
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
||||||
|
}
|
||||||
|
return string(i), s, nil
|
||||||
}
|
}
|
||||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapted from src/pkg/strconv/quote.go.
|
|
||||||
func unhex(b byte) (v byte, ok bool) {
|
|
||||||
switch {
|
|
||||||
case '0' <= b && b <= '9':
|
|
||||||
return b - '0', true
|
|
||||||
case 'a' <= b && b <= 'f':
|
|
||||||
return b - 'a' + 10, true
|
|
||||||
case 'A' <= b && b <= 'F':
|
|
||||||
return b - 'A' + 10, true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Back off the parser by one token. Can only be done between calls to next().
|
// Back off the parser by one token. Can only be done between calls to next().
|
||||||
// It makes the next advance() a no-op.
|
// It makes the next advance() a no-op.
|
||||||
func (p *textParser) back() { p.backed = true }
|
func (p *textParser) back() { p.backed = true }
|
||||||
@@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) {
|
|||||||
if tok.err != nil {
|
if tok.err != nil {
|
||||||
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
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
|
return strings.Join(parts, ""), nil
|
||||||
}
|
}
|
||||||
@@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|||||||
return p.readStruct(fv, terminator)
|
return p.readStruct(fv, terminator)
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||||
fv.SetUint(x)
|
fv.SetUint(uint64(x))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
@@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|||||||
// UnmarshalText returns *RequiredNotSetError.
|
// UnmarshalText returns *RequiredNotSetError.
|
||||||
func UnmarshalText(s string, pb Message) error {
|
func UnmarshalText(s string, pb Message) error {
|
||||||
if um, ok := pb.(encoding.TextUnmarshaler); ok {
|
if um, ok := pb.(encoding.TextUnmarshaler); ok {
|
||||||
err := um.UnmarshalText([]byte(s))
|
return um.UnmarshalText([]byte(s))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
pb.Reset()
|
pb.Reset()
|
||||||
v := reflect.ValueOf(pb)
|
v := reflect.ValueOf(pb)
|
||||||
if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
|
return newTextParser(s).readStruct(v.Elem(), "")
|
||||||
return pe
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-17
@@ -1,15 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: google/protobuf/any.proto
|
// source: google/protobuf/any.proto
|
||||||
|
|
||||||
/*
|
|
||||||
Package any is a generated protocol buffer package.
|
|
||||||
|
|
||||||
It is generated from these files:
|
|
||||||
google/protobuf/any.proto
|
|
||||||
|
|
||||||
It has these top-level messages:
|
|
||||||
Any
|
|
||||||
*/
|
|
||||||
package any
|
package any
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
import proto "github.com/golang/protobuf/proto"
|
||||||
@@ -132,14 +123,36 @@ type Any struct {
|
|||||||
//
|
//
|
||||||
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
|
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
|
||||||
// Must be a valid serialized protocol buffer of the above specified type.
|
// Must be a valid serialized protocol buffer of the above specified type.
|
||||||
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Any) Reset() { *m = Any{} }
|
func (m *Any) Reset() { *m = Any{} }
|
||||||
func (m *Any) String() string { return proto.CompactTextString(m) }
|
func (m *Any) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Any) ProtoMessage() {}
|
func (*Any) ProtoMessage() {}
|
||||||
func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*Any) Descriptor() ([]byte, []int) {
|
||||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
return fileDescriptor_any_744b9ca530f228db, []int{0}
|
||||||
|
}
|
||||||
|
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||||
|
func (m *Any) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_Any.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_Any.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *Any) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_Any.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *Any) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_Any.Size(m)
|
||||||
|
}
|
||||||
|
func (m *Any) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_Any.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_Any proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *Any) GetTypeUrl() string {
|
func (m *Any) GetTypeUrl() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -159,9 +172,9 @@ func init() {
|
|||||||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor_any_744b9ca530f228db = []byte{
|
||||||
// 185 bytes of a gzipped FileDescriptorProto
|
// 185 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||||
|
|||||||
+32
-17
@@ -1,15 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: google/protobuf/duration.proto
|
// source: google/protobuf/duration.proto
|
||||||
|
|
||||||
/*
|
|
||||||
Package duration is a generated protocol buffer package.
|
|
||||||
|
|
||||||
It is generated from these files:
|
|
||||||
google/protobuf/duration.proto
|
|
||||||
|
|
||||||
It has these top-level messages:
|
|
||||||
Duration
|
|
||||||
*/
|
|
||||||
package duration
|
package duration
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
import proto "github.com/golang/protobuf/proto"
|
||||||
@@ -98,14 +89,36 @@ type Duration struct {
|
|||||||
// of one second or more, a non-zero value for the `nanos` field must be
|
// of one second or more, a non-zero value for the `nanos` field must be
|
||||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||||
// to +999,999,999 inclusive.
|
// to +999,999,999 inclusive.
|
||||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Duration) Reset() { *m = Duration{} }
|
func (m *Duration) Reset() { *m = Duration{} }
|
||||||
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Duration) ProtoMessage() {}
|
func (*Duration) ProtoMessage() {}
|
||||||
func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*Duration) Descriptor() ([]byte, []int) {
|
||||||
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
return fileDescriptor_duration_e7d612259e3f0613, []int{0}
|
||||||
|
}
|
||||||
|
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||||
|
func (m *Duration) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_Duration.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *Duration) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_Duration.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *Duration) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_Duration.Size(m)
|
||||||
|
}
|
||||||
|
func (m *Duration) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_Duration.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_Duration proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *Duration) GetSeconds() int64 {
|
func (m *Duration) GetSeconds() int64 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -125,9 +138,11 @@ func init() {
|
|||||||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor0) }
|
func init() {
|
||||||
|
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613)
|
||||||
|
}
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor_duration_e7d612259e3f0613 = []byte{
|
||||||
// 190 bytes of a gzipped FileDescriptorProto
|
// 190 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
#
|
|
||||||
# This script fetches and rebuilds the "well-known types" protocol buffers.
|
|
||||||
# To run this you will need protoc and goprotobuf installed;
|
|
||||||
# see https://github.com/golang/protobuf for instructions.
|
|
||||||
# You also need Go and Git installed.
|
|
||||||
|
|
||||||
PKG=github.com/golang/protobuf/ptypes
|
|
||||||
UPSTREAM=https://github.com/google/protobuf
|
|
||||||
UPSTREAM_SUBDIR=src/google/protobuf
|
|
||||||
PROTO_FILES=(any duration empty struct timestamp wrappers)
|
|
||||||
|
|
||||||
function die() {
|
|
||||||
echo 1>&2 $*
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sanity check that the right tools are accessible.
|
|
||||||
for tool in go git protoc protoc-gen-go; do
|
|
||||||
q=$(which $tool) || die "didn't find $tool"
|
|
||||||
echo 1>&2 "$tool: $q"
|
|
||||||
done
|
|
||||||
|
|
||||||
tmpdir=$(mktemp -d -t regen-wkt.XXXXXX)
|
|
||||||
trap 'rm -rf $tmpdir' EXIT
|
|
||||||
|
|
||||||
echo -n 1>&2 "finding package dir... "
|
|
||||||
pkgdir=$(go list -f '{{.Dir}}' $PKG)
|
|
||||||
echo 1>&2 $pkgdir
|
|
||||||
base=$(echo $pkgdir | sed "s,/$PKG\$,,")
|
|
||||||
echo 1>&2 "base: $base"
|
|
||||||
cd "$base"
|
|
||||||
|
|
||||||
echo 1>&2 "fetching latest protos... "
|
|
||||||
git clone -q $UPSTREAM $tmpdir
|
|
||||||
|
|
||||||
for file in ${PROTO_FILES[@]}; do
|
|
||||||
echo 1>&2 "* $file"
|
|
||||||
protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die
|
|
||||||
cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file
|
|
||||||
done
|
|
||||||
|
|
||||||
echo 1>&2 "All OK"
|
|
||||||
+33
-18
@@ -1,15 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: google/protobuf/timestamp.proto
|
// source: google/protobuf/timestamp.proto
|
||||||
|
|
||||||
/*
|
|
||||||
Package timestamp is a generated protocol buffer package.
|
|
||||||
|
|
||||||
It is generated from these files:
|
|
||||||
google/protobuf/timestamp.proto
|
|
||||||
|
|
||||||
It has these top-level messages:
|
|
||||||
Timestamp
|
|
||||||
*/
|
|
||||||
package timestamp
|
package timestamp
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
import proto "github.com/golang/protobuf/proto"
|
||||||
@@ -101,7 +92,7 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
|
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||||
// to obtain a formatter capable of generating timestamps in this format.
|
// to obtain a formatter capable of generating timestamps in this format.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -114,14 +105,36 @@ type Timestamp struct {
|
|||||||
// second values with fractions must still have non-negative nanos values
|
// second values with fractions must still have non-negative nanos values
|
||||||
// that count forward in time. Must be from 0 to 999,999,999
|
// that count forward in time. Must be from 0 to 999,999,999
|
||||||
// inclusive.
|
// inclusive.
|
||||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Timestamp) ProtoMessage() {}
|
func (*Timestamp) ProtoMessage() {}
|
||||||
func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*Timestamp) Descriptor() ([]byte, []int) {
|
||||||
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0}
|
||||||
|
}
|
||||||
|
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||||
|
func (m *Timestamp) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_Timestamp.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *Timestamp) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_Timestamp.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *Timestamp) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_Timestamp.Size(m)
|
||||||
|
}
|
||||||
|
func (m *Timestamp) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_Timestamp.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_Timestamp proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *Timestamp) GetSeconds() int64 {
|
func (m *Timestamp) GetSeconds() int64 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -141,9 +154,11 @@ func init() {
|
|||||||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor0) }
|
func init() {
|
||||||
|
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8)
|
||||||
|
}
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{
|
||||||
// 191 bytes of a gzipped FileDescriptorProto
|
// 191 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ option objc_class_prefix = "GPB";
|
|||||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
|
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||||
// to obtain a formatter capable of generating timestamps in this format.
|
// to obtain a formatter capable of generating timestamps in this format.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- tip
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
ISC License
|
|
||||||
|
|
||||||
Copyright (c) 2012 Chris Howey
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
-384
@@ -1,384 +0,0 @@
|
|||||||
Unless otherwise noted, all files in this distribution are released
|
|
||||||
under the Common Development and Distribution License (CDDL).
|
|
||||||
Exceptions are noted within the associated source files.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
1.1. "Contributor" means each individual or entity that creates
|
|
||||||
or contributes to the creation of Modifications.
|
|
||||||
|
|
||||||
1.2. "Contributor Version" means the combination of the Original
|
|
||||||
Software, prior Modifications used by a Contributor (if any),
|
|
||||||
and the Modifications made by that particular Contributor.
|
|
||||||
|
|
||||||
1.3. "Covered Software" means (a) the Original Software, or (b)
|
|
||||||
Modifications, or (c) the combination of files containing
|
|
||||||
Original Software with files containing Modifications, in
|
|
||||||
each case including portions thereof.
|
|
||||||
|
|
||||||
1.4. "Executable" means the Covered Software in any form other
|
|
||||||
than Source Code.
|
|
||||||
|
|
||||||
1.5. "Initial Developer" means the individual or entity that first
|
|
||||||
makes Original Software available under this License.
|
|
||||||
|
|
||||||
1.6. "Larger Work" means a work which combines Covered Software or
|
|
||||||
portions thereof with code not governed by the terms of this
|
|
||||||
License.
|
|
||||||
|
|
||||||
1.7. "License" means this document.
|
|
||||||
|
|
||||||
1.8. "Licensable" means having the right to grant, to the maximum
|
|
||||||
extent possible, whether at the time of the initial grant or
|
|
||||||
subsequently acquired, any and all of the rights conveyed
|
|
||||||
herein.
|
|
||||||
|
|
||||||
1.9. "Modifications" means the Source Code and Executable form of
|
|
||||||
any of the following:
|
|
||||||
|
|
||||||
A. Any file that results from an addition to, deletion from or
|
|
||||||
modification of the contents of a file containing Original
|
|
||||||
Software or previous Modifications;
|
|
||||||
|
|
||||||
B. Any new file that contains any part of the Original
|
|
||||||
Software or previous Modifications; or
|
|
||||||
|
|
||||||
C. Any new file that is contributed or otherwise made
|
|
||||||
available under the terms of this License.
|
|
||||||
|
|
||||||
1.10. "Original Software" means the Source Code and Executable
|
|
||||||
form of computer software code that is originally released
|
|
||||||
under this License.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" means any patent claim(s), now owned or
|
|
||||||
hereafter acquired, including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by
|
|
||||||
grantor.
|
|
||||||
|
|
||||||
1.12. "Source Code" means (a) the common form of computer software
|
|
||||||
code in which modifications are made and (b) associated
|
|
||||||
documentation included in or with such code.
|
|
||||||
|
|
||||||
1.13. "You" (or "Your") means an individual or a legal entity
|
|
||||||
exercising rights under, and complying with all of the terms
|
|
||||||
of, this License. For legal entities, "You" includes any
|
|
||||||
entity which controls, is controlled by, or is under common
|
|
||||||
control with You. For purposes of this definition,
|
|
||||||
"control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by
|
|
||||||
contract or otherwise, or (b) ownership of more than fifty
|
|
||||||
percent (50%) of the outstanding shares or beneficial
|
|
||||||
ownership of such entity.
|
|
||||||
|
|
||||||
2. License Grants.
|
|
||||||
|
|
||||||
2.1. The Initial Developer Grant.
|
|
||||||
|
|
||||||
Conditioned upon Your compliance with Section 3.1 below and
|
|
||||||
subject to third party intellectual property claims, the Initial
|
|
||||||
Developer hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
(a) under intellectual property rights (other than patent or
|
|
||||||
trademark) Licensable by Initial Developer, to use,
|
|
||||||
reproduce, modify, display, perform, sublicense and
|
|
||||||
distribute the Original Software (or portions thereof),
|
|
||||||
with or without Modifications, and/or as part of a Larger
|
|
||||||
Work; and
|
|
||||||
|
|
||||||
(b) under Patent Claims infringed by the making, using or
|
|
||||||
selling of Original Software, to make, have made, use,
|
|
||||||
practice, sell, and offer for sale, and/or otherwise
|
|
||||||
dispose of the Original Software (or portions thereof).
|
|
||||||
|
|
||||||
(c) The licenses granted in Sections 2.1(a) and (b) are
|
|
||||||
effective on the date Initial Developer first distributes
|
|
||||||
or otherwise makes the Original Software available to a
|
|
||||||
third party under the terms of this License.
|
|
||||||
|
|
||||||
(d) Notwithstanding Section 2.1(b) above, no patent license is
|
|
||||||
granted: (1) for code that You delete from the Original
|
|
||||||
Software, or (2) for infringements caused by: (i) the
|
|
||||||
modification of the Original Software, or (ii) the
|
|
||||||
combination of the Original Software with other software
|
|
||||||
or devices.
|
|
||||||
|
|
||||||
2.2. Contributor Grant.
|
|
||||||
|
|
||||||
Conditioned upon Your compliance with Section 3.1 below and
|
|
||||||
subject to third party intellectual property claims, each
|
|
||||||
Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
(a) under intellectual property rights (other than patent or
|
|
||||||
trademark) Licensable by Contributor to use, reproduce,
|
|
||||||
modify, display, perform, sublicense and distribute the
|
|
||||||
Modifications created by such Contributor (or portions
|
|
||||||
thereof), either on an unmodified basis, with other
|
|
||||||
Modifications, as Covered Software and/or as part of a
|
|
||||||
Larger Work; and
|
|
||||||
|
|
||||||
(b) under Patent Claims infringed by the making, using, or
|
|
||||||
selling of Modifications made by that Contributor either
|
|
||||||
alone and/or in combination with its Contributor Version
|
|
||||||
(or portions of such combination), to make, use, sell,
|
|
||||||
offer for sale, have made, and/or otherwise dispose of:
|
|
||||||
(1) Modifications made by that Contributor (or portions
|
|
||||||
thereof); and (2) the combination of Modifications made by
|
|
||||||
that Contributor with its Contributor Version (or portions
|
|
||||||
of such combination).
|
|
||||||
|
|
||||||
(c) The licenses granted in Sections 2.2(a) and 2.2(b) are
|
|
||||||
effective on the date Contributor first distributes or
|
|
||||||
otherwise makes the Modifications available to a third
|
|
||||||
party.
|
|
||||||
|
|
||||||
(d) Notwithstanding Section 2.2(b) above, no patent license is
|
|
||||||
granted: (1) for any code that Contributor has deleted
|
|
||||||
from the Contributor Version; (2) for infringements caused
|
|
||||||
by: (i) third party modifications of Contributor Version,
|
|
||||||
or (ii) the combination of Modifications made by that
|
|
||||||
Contributor with other software (except as part of the
|
|
||||||
Contributor Version) or other devices; or (3) under Patent
|
|
||||||
Claims infringed by Covered Software in the absence of
|
|
||||||
Modifications made by that Contributor.
|
|
||||||
|
|
||||||
3. Distribution Obligations.
|
|
||||||
|
|
||||||
3.1. Availability of Source Code.
|
|
||||||
|
|
||||||
Any Covered Software that You distribute or otherwise make
|
|
||||||
available in Executable form must also be made available in Source
|
|
||||||
Code form and that Source Code form must be distributed only under
|
|
||||||
the terms of this License. You must include a copy of this
|
|
||||||
License with every copy of the Source Code form of the Covered
|
|
||||||
Software You distribute or otherwise make available. You must
|
|
||||||
inform recipients of any such Covered Software in Executable form
|
|
||||||
as to how they can obtain such Covered Software in Source Code
|
|
||||||
form in a reasonable manner on or through a medium customarily
|
|
||||||
used for software exchange.
|
|
||||||
|
|
||||||
3.2. Modifications.
|
|
||||||
|
|
||||||
The Modifications that You create or to which You contribute are
|
|
||||||
governed by the terms of this License. You represent that You
|
|
||||||
believe Your Modifications are Your original creation(s) and/or
|
|
||||||
You have sufficient rights to grant the rights conveyed by this
|
|
||||||
License.
|
|
||||||
|
|
||||||
3.3. Required Notices.
|
|
||||||
|
|
||||||
You must include a notice in each of Your Modifications that
|
|
||||||
identifies You as the Contributor of the Modification. You may
|
|
||||||
not remove or alter any copyright, patent or trademark notices
|
|
||||||
contained within the Covered Software, or any notices of licensing
|
|
||||||
or any descriptive text giving attribution to any Contributor or
|
|
||||||
the Initial Developer.
|
|
||||||
|
|
||||||
3.4. Application of Additional Terms.
|
|
||||||
|
|
||||||
You may not offer or impose any terms on any Covered Software in
|
|
||||||
Source Code form that alters or restricts the applicable version
|
|
||||||
of this License or the recipients' rights hereunder. You may
|
|
||||||
choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of
|
|
||||||
Covered Software. However, you may do so only on Your own behalf,
|
|
||||||
and not on behalf of the Initial Developer or any Contributor.
|
|
||||||
You must make it absolutely clear that any such warranty, support,
|
|
||||||
indemnity or liability obligation is offered by You alone, and You
|
|
||||||
hereby agree to indemnify the Initial Developer and every
|
|
||||||
Contributor for any liability incurred by the Initial Developer or
|
|
||||||
such Contributor as a result of warranty, support, indemnity or
|
|
||||||
liability terms You offer.
|
|
||||||
|
|
||||||
3.5. Distribution of Executable Versions.
|
|
||||||
|
|
||||||
You may distribute the Executable form of the Covered Software
|
|
||||||
under the terms of this License or under the terms of a license of
|
|
||||||
Your choice, which may contain terms different from this License,
|
|
||||||
provided that You are in compliance with the terms of this License
|
|
||||||
and that the license for the Executable form does not attempt to
|
|
||||||
limit or alter the recipient's rights in the Source Code form from
|
|
||||||
the rights set forth in this License. If You distribute the
|
|
||||||
Covered Software in Executable form under a different license, You
|
|
||||||
must make it absolutely clear that any terms which differ from
|
|
||||||
this License are offered by You alone, not by the Initial
|
|
||||||
Developer or Contributor. You hereby agree to indemnify the
|
|
||||||
Initial Developer and every Contributor for any liability incurred
|
|
||||||
by the Initial Developer or such Contributor as a result of any
|
|
||||||
such terms You offer.
|
|
||||||
|
|
||||||
3.6. Larger Works.
|
|
||||||
|
|
||||||
You may create a Larger Work by combining Covered Software with
|
|
||||||
other code not governed by the terms of this License and
|
|
||||||
distribute the Larger Work as a single product. In such a case,
|
|
||||||
You must make sure the requirements of this License are fulfilled
|
|
||||||
for the Covered Software.
|
|
||||||
|
|
||||||
4. Versions of the License.
|
|
||||||
|
|
||||||
4.1. New Versions.
|
|
||||||
|
|
||||||
Sun Microsystems, Inc. is the initial license steward and may
|
|
||||||
publish revised and/or new versions of this License from time to
|
|
||||||
time. Each version will be given a distinguishing version number.
|
|
||||||
Except as provided in Section 4.3, no one other than the license
|
|
||||||
steward has the right to modify this License.
|
|
||||||
|
|
||||||
4.2. Effect of New Versions.
|
|
||||||
|
|
||||||
You may always continue to use, distribute or otherwise make the
|
|
||||||
Covered Software available under the terms of the version of the
|
|
||||||
License under which You originally received the Covered Software.
|
|
||||||
If the Initial Developer includes a notice in the Original
|
|
||||||
Software prohibiting it from being distributed or otherwise made
|
|
||||||
available under any subsequent version of the License, You must
|
|
||||||
distribute and make the Covered Software available under the terms
|
|
||||||
of the version of the License under which You originally received
|
|
||||||
the Covered Software. Otherwise, You may also choose to use,
|
|
||||||
distribute or otherwise make the Covered Software available under
|
|
||||||
the terms of any subsequent version of the License published by
|
|
||||||
the license steward.
|
|
||||||
|
|
||||||
4.3. Modified Versions.
|
|
||||||
|
|
||||||
When You are an Initial Developer and You want to create a new
|
|
||||||
license for Your Original Software, You may create and use a
|
|
||||||
modified version of this License if You: (a) rename the license
|
|
||||||
and remove any references to the name of the license steward
|
|
||||||
(except to note that the license differs from this License); and
|
|
||||||
(b) otherwise make it clear that the license contains terms which
|
|
||||||
differ from this License.
|
|
||||||
|
|
||||||
5. DISCLAIMER OF WARRANTY.
|
|
||||||
|
|
||||||
COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
|
|
||||||
BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
|
||||||
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
|
|
||||||
SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
|
|
||||||
PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
|
|
||||||
PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY
|
|
||||||
COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
|
|
||||||
INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
|
|
||||||
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
|
|
||||||
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
|
|
||||||
ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
|
|
||||||
DISCLAIMER.
|
|
||||||
|
|
||||||
6. TERMINATION.
|
|
||||||
|
|
||||||
6.1. This License and the rights granted hereunder will terminate
|
|
||||||
automatically if You fail to comply with terms herein and fail to
|
|
||||||
cure such breach within 30 days of becoming aware of the breach.
|
|
||||||
Provisions which, by their nature, must remain in effect beyond
|
|
||||||
the termination of this License shall survive.
|
|
||||||
|
|
||||||
6.2. If You assert a patent infringement claim (excluding
|
|
||||||
declaratory judgment actions) against Initial Developer or a
|
|
||||||
Contributor (the Initial Developer or Contributor against whom You
|
|
||||||
assert such claim is referred to as "Participant") alleging that
|
|
||||||
the Participant Software (meaning the Contributor Version where
|
|
||||||
the Participant is a Contributor or the Original Software where
|
|
||||||
the Participant is the Initial Developer) directly or indirectly
|
|
||||||
infringes any patent, then any and all rights granted directly or
|
|
||||||
indirectly to You by such Participant, the Initial Developer (if
|
|
||||||
the Initial Developer is not the Participant) and all Contributors
|
|
||||||
under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
|
|
||||||
notice from Participant terminate prospectively and automatically
|
|
||||||
at the expiration of such 60 day notice period, unless if within
|
|
||||||
such 60 day period You withdraw Your claim with respect to the
|
|
||||||
Participant Software against such Participant either unilaterally
|
|
||||||
or pursuant to a written agreement with Participant.
|
|
||||||
|
|
||||||
6.3. In the event of termination under Sections 6.1 or 6.2 above,
|
|
||||||
all end user licenses that have been validly granted by You or any
|
|
||||||
distributor hereunder prior to termination (excluding licenses
|
|
||||||
granted to You by any distributor) shall survive termination.
|
|
||||||
|
|
||||||
7. LIMITATION OF LIABILITY.
|
|
||||||
|
|
||||||
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
|
|
||||||
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
|
|
||||||
INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
|
|
||||||
COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
|
|
||||||
LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
|
|
||||||
CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
|
|
||||||
LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
|
|
||||||
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
|
|
||||||
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
|
|
||||||
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
|
|
||||||
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
|
|
||||||
INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
|
|
||||||
APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
|
|
||||||
NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
|
|
||||||
CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
|
|
||||||
APPLY TO YOU.
|
|
||||||
|
|
||||||
8. U.S. GOVERNMENT END USERS.
|
|
||||||
|
|
||||||
The Covered Software is a "commercial item," as that term is
|
|
||||||
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
|
|
||||||
computer software" (as that term is defined at 48
|
|
||||||
C.F.R. 252.227-7014(a)(1)) and "commercial computer software
|
|
||||||
documentation" as such terms are used in 48 C.F.R. 12.212
|
|
||||||
(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48
|
|
||||||
C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
|
|
||||||
U.S. Government End Users acquire Covered Software with only those
|
|
||||||
rights set forth herein. This U.S. Government Rights clause is in
|
|
||||||
lieu of, and supersedes, any other FAR, DFAR, or other clause or
|
|
||||||
provision that addresses Government rights in computer software
|
|
||||||
under this License.
|
|
||||||
|
|
||||||
9. MISCELLANEOUS.
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. This License shall be governed
|
|
||||||
by the law of the jurisdiction specified in a notice contained
|
|
||||||
within the Original Software (except to the extent applicable law,
|
|
||||||
if any, provides otherwise), excluding such jurisdiction's
|
|
||||||
conflict-of-law provisions. Any litigation relating to this
|
|
||||||
License shall be subject to the jurisdiction of the courts located
|
|
||||||
in the jurisdiction and venue specified in a notice contained
|
|
||||||
within the Original Software, with the losing party responsible
|
|
||||||
for costs, including, without limitation, court costs and
|
|
||||||
reasonable attorneys' fees and expenses. The application of the
|
|
||||||
United Nations Convention on Contracts for the International Sale
|
|
||||||
of Goods is expressly excluded. Any law or regulation which
|
|
||||||
provides that the language of a contract shall be construed
|
|
||||||
against the drafter shall not apply to this License. You agree
|
|
||||||
that You alone are responsible for compliance with the United
|
|
||||||
States export administration regulations (and the export control
|
|
||||||
laws and regulation of any other countries) when You use,
|
|
||||||
distribute or otherwise make available any Covered Software.
|
|
||||||
|
|
||||||
10. RESPONSIBILITY FOR CLAIMS.
|
|
||||||
|
|
||||||
As between Initial Developer and the Contributors, each party is
|
|
||||||
responsible for claims and damages arising, directly or
|
|
||||||
indirectly, out of its utilization of rights under this License
|
|
||||||
and You agree to work with Initial Developer and Contributors to
|
|
||||||
distribute such responsibility on an equitable basis. Nothing
|
|
||||||
herein is intended or shall be deemed to constitute any admission
|
|
||||||
of liability.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
|
|
||||||
DISTRIBUTION LICENSE (CDDL)
|
|
||||||
|
|
||||||
For Covered Software in this distribution, this License shall
|
|
||||||
be governed by the laws of the State of California (excluding
|
|
||||||
conflict-of-law provisions).
|
|
||||||
|
|
||||||
Any litigation relating to this License shall be subject to the
|
|
||||||
jurisdiction of the Federal Courts of the Northern District of
|
|
||||||
California and the state courts of the State of California, with
|
|
||||||
venue lying in Santa Clara County, California.
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
# getpasswd in Go [](https://godoc.org/github.com/howeyc/gopass) [](http://travis-ci.org/howeyc/gopass)
|
|
||||||
|
|
||||||
Retrieve password from user terminal or piped input without echo.
|
|
||||||
|
|
||||||
Verified on BSD, Linux, and Windows.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "github.com/howeyc/gopass"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Printf("Password: ")
|
|
||||||
|
|
||||||
// Silent. For printing *'s use gopass.GetPasswdMasked()
|
|
||||||
pass, err := gopass.GetPasswd()
|
|
||||||
if err != nil {
|
|
||||||
// Handle gopass.ErrInterrupted or getch() read error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do something with pass
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Caution: Multi-byte characters not supported!
|
|
||||||
-110
@@ -1,110 +0,0 @@
|
|||||||
package gopass
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FdReader interface {
|
|
||||||
io.Reader
|
|
||||||
Fd() uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultGetCh = func(r io.Reader) (byte, error) {
|
|
||||||
buf := make([]byte, 1)
|
|
||||||
if n, err := r.Read(buf); n == 0 || err != nil {
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
return buf[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
maxLength = 512
|
|
||||||
ErrInterrupted = errors.New("interrupted")
|
|
||||||
ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
|
|
||||||
|
|
||||||
// Provide variable so that tests can provide a mock implementation.
|
|
||||||
getch = defaultGetCh
|
|
||||||
)
|
|
||||||
|
|
||||||
// getPasswd returns the input read from terminal.
|
|
||||||
// If prompt is not empty, it will be output as a prompt to the user
|
|
||||||
// If masked is true, typing will be matched by asterisks on the screen.
|
|
||||||
// Otherwise, typing will echo nothing.
|
|
||||||
func getPasswd(prompt string, masked bool, r FdReader, w io.Writer) ([]byte, error) {
|
|
||||||
var err error
|
|
||||||
var pass, bs, mask []byte
|
|
||||||
if masked {
|
|
||||||
bs = []byte("\b \b")
|
|
||||||
mask = []byte("*")
|
|
||||||
}
|
|
||||||
|
|
||||||
if isTerminal(r.Fd()) {
|
|
||||||
if oldState, err := makeRaw(r.Fd()); err != nil {
|
|
||||||
return pass, err
|
|
||||||
} else {
|
|
||||||
defer func() {
|
|
||||||
restore(r.Fd(), oldState)
|
|
||||||
fmt.Fprintln(w)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if prompt != "" {
|
|
||||||
fmt.Fprint(w, prompt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track total bytes read, not just bytes in the password. This ensures any
|
|
||||||
// errors that might flood the console with nil or -1 bytes infinitely are
|
|
||||||
// capped.
|
|
||||||
var counter int
|
|
||||||
for counter = 0; counter <= maxLength; counter++ {
|
|
||||||
if v, e := getch(r); e != nil {
|
|
||||||
err = e
|
|
||||||
break
|
|
||||||
} else if v == 127 || v == 8 {
|
|
||||||
if l := len(pass); l > 0 {
|
|
||||||
pass = pass[:l-1]
|
|
||||||
fmt.Fprint(w, string(bs))
|
|
||||||
}
|
|
||||||
} else if v == 13 || v == 10 {
|
|
||||||
break
|
|
||||||
} else if v == 3 {
|
|
||||||
err = ErrInterrupted
|
|
||||||
break
|
|
||||||
} else if v != 0 {
|
|
||||||
pass = append(pass, v)
|
|
||||||
fmt.Fprint(w, string(mask))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if counter > maxLength {
|
|
||||||
err = ErrMaxLengthExceeded
|
|
||||||
}
|
|
||||||
|
|
||||||
return pass, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPasswd returns the password read from the terminal without echoing input.
|
|
||||||
// The returned byte array does not include end-of-line characters.
|
|
||||||
func GetPasswd() ([]byte, error) {
|
|
||||||
return getPasswd("", false, os.Stdin, os.Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPasswdMasked returns the password read from the terminal, echoing asterisks.
|
|
||||||
// The returned byte array does not include end-of-line characters.
|
|
||||||
func GetPasswdMasked() ([]byte, error) {
|
|
||||||
return getPasswd("", true, os.Stdin, os.Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPasswdPrompt prompts the user and returns the password read from the terminal.
|
|
||||||
// If mask is true, then asterisks are echoed.
|
|
||||||
// The returned byte array does not include end-of-line characters.
|
|
||||||
func GetPasswdPrompt(prompt string, mask bool, r FdReader, w io.Writer) ([]byte, error) {
|
|
||||||
return getPasswd(prompt, mask, r, w)
|
|
||||||
}
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
// +build !solaris
|
|
||||||
|
|
||||||
package gopass
|
|
||||||
|
|
||||||
import "golang.org/x/crypto/ssh/terminal"
|
|
||||||
|
|
||||||
type terminalState struct {
|
|
||||||
state *terminal.State
|
|
||||||
}
|
|
||||||
|
|
||||||
func isTerminal(fd uintptr) bool {
|
|
||||||
return terminal.IsTerminal(int(fd))
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeRaw(fd uintptr) (*terminalState, error) {
|
|
||||||
state, err := terminal.MakeRaw(int(fd))
|
|
||||||
|
|
||||||
return &terminalState{
|
|
||||||
state: state,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func restore(fd uintptr, oldState *terminalState) error {
|
|
||||||
return terminal.Restore(int(fd), oldState.state)
|
|
||||||
}
|
|
||||||
-69
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of the
|
|
||||||
* Common Development and Distribution License, Version 1.0 only
|
|
||||||
* (the "License"). You may not use this file except in compliance
|
|
||||||
* with the License.
|
|
||||||
*
|
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
* or http://www.opensolaris.org/os/licensing.
|
|
||||||
* See the License for the specific language governing permissions
|
|
||||||
* and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
* If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
// Below is derived from Solaris source, so CDDL license is included.
|
|
||||||
|
|
||||||
package gopass
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
type terminalState struct {
|
|
||||||
state *unix.Termios
|
|
||||||
}
|
|
||||||
|
|
||||||
// isTerminal returns true if there is a terminal attached to the given
|
|
||||||
// file descriptor.
|
|
||||||
// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
|
|
||||||
func isTerminal(fd uintptr) bool {
|
|
||||||
var termio unix.Termio
|
|
||||||
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// makeRaw puts the terminal connected to the given file descriptor into raw
|
|
||||||
// mode and returns the previous state of the terminal so that it can be
|
|
||||||
// restored.
|
|
||||||
// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
|
|
||||||
func makeRaw(fd uintptr) (*terminalState, error) {
|
|
||||||
oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
oldTermios := *oldTermiosPtr
|
|
||||||
|
|
||||||
newTermios := oldTermios
|
|
||||||
newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL
|
|
||||||
if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &terminalState{
|
|
||||||
state: oldTermiosPtr,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func restore(fd uintptr, oldState *terminalState) error {
|
|
||||||
return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state)
|
|
||||||
}
|
|
||||||
+3
-2
@@ -1,3 +1,4 @@
|
|||||||
.idea
|
/vendor
|
||||||
|
/bug_test.go
|
||||||
/coverage.txt
|
/coverage.txt
|
||||||
/profile.out
|
/.idea
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@ language: go
|
|||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
|
- 1.x
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- go get -t -v ./...
|
- go get -t -v ./...
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/json-iterator/go"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
|
||||||
|
version = "1.1.3"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/modern-go/concurrent"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/modern-go/reflect2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "56a0b9e9e61d2bc8af5e1b68537401b7f4d60805eda3d107058f3171aa5cf793"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
|
||||||
|
ignored = ["github.com/davecgh/go-spew*","github.com/google/gofuzz*","github.com/stretchr/testify*"]
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/modern-go/reflect2"
|
||||||
|
version = "1.0.0"
|
||||||
+13
-2
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
||||||
|
|
||||||
|
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
||||||
|
|
||||||
```
|
```
|
||||||
Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com
|
Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com
|
||||||
```
|
```
|
||||||
@@ -29,6 +31,9 @@ Raw Result (easyjson requires static code generation)
|
|||||||
| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op |
|
| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op |
|
||||||
| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op |
|
| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op |
|
||||||
|
|
||||||
|
Always benchmark with your own workload.
|
||||||
|
The result depends heavily on the data input.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
100% compatibility with standard lib
|
100% compatibility with standard lib
|
||||||
@@ -44,7 +49,9 @@ with
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/json-iterator/go"
|
import "github.com/json-iterator/go"
|
||||||
jsoniter.Marshal(&data)
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
json.Marshal(&data)
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace
|
Replace
|
||||||
@@ -58,7 +65,9 @@ with
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/json-iterator/go"
|
import "github.com/json-iterator/go"
|
||||||
jsoniter.Unmarshal(input, &data)
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
json.Unmarshal(input, &data)
|
||||||
```
|
```
|
||||||
|
|
||||||
[More documentation](http://jsoniter.com/migrate-from-go-std.html)
|
[More documentation](http://jsoniter.com/migrate-from-go-std.html)
|
||||||
@@ -76,5 +85,7 @@ Contributors
|
|||||||
* [thockin](https://github.com/thockin)
|
* [thockin](https://github.com/thockin)
|
||||||
* [mattn](https://github.com/mattn)
|
* [mattn](https://github.com/mattn)
|
||||||
* [cch123](https://github.com/cch123)
|
* [cch123](https://github.com/cch123)
|
||||||
|
* [Oleg Shaldybin](https://github.com/olegshaldybin)
|
||||||
|
* [Jason Toffaletti](https://github.com/toffaletti)
|
||||||
|
|
||||||
Report issue or pull request, or email taowen@gmail.com, or [](https://gitter.im/json-iterator/Lobby)
|
Report issue or pull request, or email taowen@gmail.com, or [](https://gitter.im/json-iterator/Lobby)
|
||||||
|
|||||||
Generated
Vendored
+37
-16
@@ -16,15 +16,6 @@ func Unmarshal(data []byte, v interface{}) error {
|
|||||||
return ConfigDefault.Unmarshal(data, v)
|
return ConfigDefault.Unmarshal(data, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lastNotSpacePos(data []byte) int {
|
|
||||||
for i := len(data) - 1; i >= 0; i-- {
|
|
||||||
if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
|
|
||||||
return i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalFromString convenient method to read from string instead of []byte
|
// UnmarshalFromString convenient method to read from string instead of []byte
|
||||||
func UnmarshalFromString(str string, v interface{}) error {
|
func UnmarshalFromString(str string, v interface{}) error {
|
||||||
return ConfigDefault.UnmarshalFromString(str, v)
|
return ConfigDefault.UnmarshalFromString(str, v)
|
||||||
@@ -71,6 +62,11 @@ type Decoder struct {
|
|||||||
|
|
||||||
// Decode decode JSON into interface{}
|
// Decode decode JSON into interface{}
|
||||||
func (adapter *Decoder) Decode(obj interface{}) error {
|
func (adapter *Decoder) Decode(obj interface{}) error {
|
||||||
|
if adapter.iter.head == adapter.iter.tail && adapter.iter.reader != nil {
|
||||||
|
if !adapter.iter.loadMore() {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
}
|
||||||
adapter.iter.ReadVal(obj)
|
adapter.iter.ReadVal(obj)
|
||||||
err := adapter.iter.Error
|
err := adapter.iter.Error
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -81,7 +77,14 @@ func (adapter *Decoder) Decode(obj interface{}) error {
|
|||||||
|
|
||||||
// More is there more?
|
// More is there more?
|
||||||
func (adapter *Decoder) More() bool {
|
func (adapter *Decoder) More() bool {
|
||||||
return adapter.iter.head != adapter.iter.tail
|
iter := adapter.iter
|
||||||
|
if iter.Error != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if iter.head != iter.tail {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return iter.loadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffered remaining buffer
|
// Buffered remaining buffer
|
||||||
@@ -90,11 +93,21 @@ func (adapter *Decoder) Buffered() io.Reader {
|
|||||||
return bytes.NewReader(remaining)
|
return bytes.NewReader(remaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseNumber for number JSON element, use float64 or json.NumberValue (alias of string)
|
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||||
|
// Number instead of as a float64.
|
||||||
func (adapter *Decoder) UseNumber() {
|
func (adapter *Decoder) UseNumber() {
|
||||||
origCfg := adapter.iter.cfg.configBeforeFrozen
|
cfg := adapter.iter.cfg.configBeforeFrozen
|
||||||
origCfg.UseNumber = true
|
cfg.UseNumber = true
|
||||||
adapter.iter.cfg = origCfg.Froze().(*frozenConfig)
|
adapter.iter.cfg = cfg.frozeWithCacheReuse()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
||||||
|
// is a struct and the input contains object keys which do not match any
|
||||||
|
// non-ignored, exported fields in the destination.
|
||||||
|
func (adapter *Decoder) DisallowUnknownFields() {
|
||||||
|
cfg := adapter.iter.cfg.configBeforeFrozen
|
||||||
|
cfg.DisallowUnknownFields = true
|
||||||
|
adapter.iter.cfg = cfg.frozeWithCacheReuse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder same as json.NewEncoder
|
// NewEncoder same as json.NewEncoder
|
||||||
@@ -110,18 +123,26 @@ type Encoder struct {
|
|||||||
// Encode encode interface{} as JSON to io.Writer
|
// Encode encode interface{} as JSON to io.Writer
|
||||||
func (adapter *Encoder) Encode(val interface{}) error {
|
func (adapter *Encoder) Encode(val interface{}) error {
|
||||||
adapter.stream.WriteVal(val)
|
adapter.stream.WriteVal(val)
|
||||||
|
adapter.stream.WriteRaw("\n")
|
||||||
adapter.stream.Flush()
|
adapter.stream.Flush()
|
||||||
return adapter.stream.Error
|
return adapter.stream.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIndent set the indention. Prefix is not supported
|
// SetIndent set the indention. Prefix is not supported
|
||||||
func (adapter *Encoder) SetIndent(prefix, indent string) {
|
func (adapter *Encoder) SetIndent(prefix, indent string) {
|
||||||
adapter.stream.cfg.indentionStep = len(indent)
|
config := adapter.stream.cfg.configBeforeFrozen
|
||||||
|
config.IndentionStep = len(indent)
|
||||||
|
adapter.stream.cfg = config.frozeWithCacheReuse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEscapeHTML escape html by default, set to false to disable
|
// SetEscapeHTML escape html by default, set to false to disable
|
||||||
func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
|
func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
|
||||||
config := adapter.stream.cfg.configBeforeFrozen
|
config := adapter.stream.cfg.configBeforeFrozen
|
||||||
config.EscapeHTML = escapeHTML
|
config.EscapeHTML = escapeHTML
|
||||||
adapter.stream.cfg = config.Froze().(*frozenConfig)
|
adapter.stream.cfg = config.frozeWithCacheReuse()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid reports whether data is a valid JSON encoding.
|
||||||
|
func Valid(data []byte) bool {
|
||||||
|
return ConfigDefault.Valid(data)
|
||||||
}
|
}
|
||||||
Generated
Vendored
+82
-3
@@ -1,9 +1,13 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/modern-go/reflect2"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Any generic object representation.
|
// Any generic object representation.
|
||||||
@@ -24,7 +28,6 @@ type Any interface {
|
|||||||
ToString() string
|
ToString() string
|
||||||
ToVal(val interface{})
|
ToVal(val interface{})
|
||||||
Get(path ...interface{}) Any
|
Get(path ...interface{}) Any
|
||||||
// TODO: add Set
|
|
||||||
Size() int
|
Size() int
|
||||||
Keys() []string
|
Keys() []string
|
||||||
GetInterface() interface{}
|
GetInterface() interface{}
|
||||||
@@ -34,7 +37,7 @@ type Any interface {
|
|||||||
type baseAny struct{}
|
type baseAny struct{}
|
||||||
|
|
||||||
func (any *baseAny) Get(path ...interface{}) Any {
|
func (any *baseAny) Get(path ...interface{}) Any {
|
||||||
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
|
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (any *baseAny) Size() int {
|
func (any *baseAny) Size() int {
|
||||||
@@ -88,7 +91,7 @@ func Wrap(val interface{}) Any {
|
|||||||
if isAny {
|
if isAny {
|
||||||
return asAny
|
return asAny
|
||||||
}
|
}
|
||||||
typ := reflect.TypeOf(val)
|
typ := reflect2.TypeOf(val)
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return wrapArray(val)
|
return wrapArray(val)
|
||||||
@@ -99,6 +102,9 @@ func Wrap(val interface{}) Any {
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
return WrapString(val.(string))
|
return WrapString(val.(string))
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
|
if strconv.IntSize == 32 {
|
||||||
|
return WrapInt32(int32(val.(int)))
|
||||||
|
}
|
||||||
return WrapInt64(int64(val.(int)))
|
return WrapInt64(int64(val.(int)))
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
return WrapInt32(int32(val.(int8)))
|
return WrapInt32(int32(val.(int8)))
|
||||||
@@ -109,7 +115,15 @@ func Wrap(val interface{}) Any {
|
|||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return WrapInt64(val.(int64))
|
return WrapInt64(val.(int64))
|
||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
|
if strconv.IntSize == 32 {
|
||||||
|
return WrapUint32(uint32(val.(uint)))
|
||||||
|
}
|
||||||
return WrapUint64(uint64(val.(uint)))
|
return WrapUint64(uint64(val.(uint)))
|
||||||
|
case reflect.Uintptr:
|
||||||
|
if ptrSize == 32 {
|
||||||
|
return WrapUint32(uint32(val.(uintptr)))
|
||||||
|
}
|
||||||
|
return WrapUint64(uint64(val.(uintptr)))
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
return WrapUint32(uint32(val.(uint8)))
|
return WrapUint32(uint32(val.(uint8)))
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
@@ -157,6 +171,8 @@ func (iter *Iterator) readAny() Any {
|
|||||||
return iter.readArrayAny()
|
return iter.readArrayAny()
|
||||||
case '-':
|
case '-':
|
||||||
return iter.readNumberAny(false)
|
return iter.readNumberAny(false)
|
||||||
|
case 0:
|
||||||
|
return &invalidAny{baseAny{}, errors.New("input is empty")}
|
||||||
default:
|
default:
|
||||||
return iter.readNumberAny(true)
|
return iter.readNumberAny(true)
|
||||||
}
|
}
|
||||||
@@ -240,3 +256,66 @@ func locatePath(iter *Iterator, path []interface{}) Any {
|
|||||||
}
|
}
|
||||||
return iter.readAny()
|
return iter.readAny()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
|
||||||
|
|
||||||
|
func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||||
|
if typ == anyType {
|
||||||
|
return &directAnyCodec{}
|
||||||
|
}
|
||||||
|
if typ.Implements(anyType) {
|
||||||
|
return &anyCodec{
|
||||||
|
valType: typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
|
||||||
|
if typ == anyType {
|
||||||
|
return &directAnyCodec{}
|
||||||
|
}
|
||||||
|
if typ.Implements(anyType) {
|
||||||
|
return &anyCodec{
|
||||||
|
valType: typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type anyCodec struct {
|
||||||
|
valType reflect2.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
|
obj := codec.valType.UnsafeIndirect(ptr)
|
||||||
|
any := obj.(Any)
|
||||||
|
any.WriteTo(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||||
|
obj := codec.valType.UnsafeIndirect(ptr)
|
||||||
|
any := obj.(Any)
|
||||||
|
return any.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type directAnyCodec struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
*(*Any)(ptr) = iter.readAny()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
|
any := *(*Any)(ptr)
|
||||||
|
any.WriteTo(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||||
|
any := *(*Any)(ptr)
|
||||||
|
return any.Size() == 0
|
||||||
|
}
|
||||||
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
+28
-9
@@ -1,6 +1,9 @@
|
|||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import "unsafe"
|
import (
|
||||||
|
"io"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
type numberLazyAny struct {
|
type numberLazyAny struct {
|
||||||
baseAny
|
baseAny
|
||||||
@@ -29,7 +32,9 @@ func (any *numberLazyAny) ToInt() int {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadInt()
|
val := iter.ReadInt()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +42,9 @@ func (any *numberLazyAny) ToInt32() int32 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadInt32()
|
val := iter.ReadInt32()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +52,9 @@ func (any *numberLazyAny) ToInt64() int64 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadInt64()
|
val := iter.ReadInt64()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +62,9 @@ func (any *numberLazyAny) ToUint() uint {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadUint()
|
val := iter.ReadUint()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +72,9 @@ func (any *numberLazyAny) ToUint32() uint32 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadUint32()
|
val := iter.ReadUint32()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +82,9 @@ func (any *numberLazyAny) ToUint64() uint64 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadUint64()
|
val := iter.ReadUint64()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +92,9 @@ func (any *numberLazyAny) ToFloat32() float32 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadFloat32()
|
val := iter.ReadFloat32()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +102,9 @@ func (any *numberLazyAny) ToFloat64() float64 {
|
|||||||
iter := any.cfg.BorrowIterator(any.buf)
|
iter := any.cfg.BorrowIterator(any.buf)
|
||||||
defer any.cfg.ReturnIterator(iter)
|
defer any.cfg.ReturnIterator(iter)
|
||||||
val := iter.ReadFloat64()
|
val := iter.ReadFloat64()
|
||||||
any.err = iter.Error
|
if iter.Error != nil && iter.Error != io.EOF {
|
||||||
|
any.err = iter.Error
|
||||||
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user