mirror of
https://github.com/kubernetes/sample-controller.git
synced 2026-02-04 00:06:14 +08:00
Compare commits
604 Commits
release-1.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d04ecc65b | ||
|
|
b08a81711d | ||
|
|
e52f649fe5 | ||
|
|
e89372412f | ||
|
|
36dfe2e210 | ||
|
|
c8c875a7f5 | ||
|
|
7db0ad7e48 | ||
|
|
e17af2c44c | ||
|
|
e45527e48e | ||
|
|
ef4b908702 | ||
|
|
703bf442f7 | ||
|
|
f2f0db5efa | ||
|
|
2e8165f1de | ||
|
|
101d823aa3 | ||
|
|
26467c4f71 | ||
|
|
b54ca2b2ed | ||
|
|
a4f6488158 | ||
|
|
83b9b3e620 | ||
|
|
8306279e8a | ||
|
|
b46e928ce5 | ||
|
|
54ce7464fe | ||
|
|
138ff46c05 | ||
|
|
051dbf71d6 | ||
|
|
9174ee00a1 | ||
|
|
0623d8089f | ||
|
|
73b2d4258d | ||
|
|
26dce95f6a | ||
|
|
c6f22201c6 | ||
|
|
6ec6fd1983 | ||
|
|
3dce427ec1 | ||
|
|
8096957653 | ||
|
|
e06c41c6d3 | ||
|
|
91909f643d | ||
|
|
6d640c488c | ||
|
|
3f9b55f6f6 | ||
|
|
82e90ed6be | ||
|
|
1cc3a97967 | ||
|
|
a31424472d | ||
|
|
2f989798b8 | ||
|
|
786e66ef24 | ||
|
|
aee8127dbe | ||
|
|
16e1de1057 | ||
|
|
d9ecc2cb9e | ||
|
|
a445f3fee5 | ||
|
|
3a2d7663f6 | ||
|
|
3ffdae14ef | ||
|
|
a574c4c3ef | ||
|
|
d3203ce5ce | ||
|
|
ad5137058f | ||
|
|
607b0c2644 | ||
|
|
bce03b60e1 | ||
|
|
23bd2cb484 | ||
|
|
f11cfdebf5 | ||
|
|
42f4c2598c | ||
|
|
552df61ad6 | ||
|
|
d5fee05681 | ||
|
|
55eaeaaa6e | ||
|
|
7ea8e03447 | ||
|
|
4fa2a6a8e7 | ||
|
|
6787e55d7a | ||
|
|
1bfb3e4ee7 | ||
|
|
0fc2ee2089 | ||
|
|
e5d1b3f3fd | ||
|
|
40e1ab21a4 | ||
|
|
17eeebdf53 | ||
|
|
6ab57347d8 | ||
|
|
cd10a7b49e | ||
|
|
cd906b0437 | ||
|
|
d087cce6e8 | ||
|
|
65e22f7740 | ||
|
|
6bea47b845 | ||
|
|
bfd612abf6 | ||
|
|
bfad7ed00b | ||
|
|
f4426ef6fd | ||
|
|
4e97399dfc | ||
|
|
a4219630cf | ||
|
|
bd44661a90 | ||
|
|
d541bbad1f | ||
|
|
eb0a2c0d76 | ||
|
|
263f7b1675 | ||
|
|
fcbb619493 | ||
|
|
ad9de770d7 | ||
|
|
0fa5f94de7 | ||
|
|
b34e5fa3ab | ||
|
|
d3dfc8394b | ||
|
|
171ea097e8 | ||
|
|
bbd21cee11 | ||
|
|
f57d2f1230 | ||
|
|
22a61a94b3 | ||
|
|
85c35b0ce1 | ||
|
|
2957cc51dc | ||
|
|
6c4483f032 | ||
|
|
94fc20b05b | ||
|
|
daaea70fab | ||
|
|
143a8f25ef | ||
|
|
17a07f263d | ||
|
|
69ef7c63d3 | ||
|
|
aa2e0fdacc | ||
|
|
6d5849604c | ||
|
|
26d6339aeb | ||
|
|
096b2e5e06 | ||
|
|
814ef8b10b | ||
|
|
af9002a249 | ||
|
|
93872e6b3c | ||
|
|
ce7ddd0264 | ||
|
|
002a25ec7b | ||
|
|
aed009a5ce | ||
|
|
459fe7f5a5 | ||
|
|
ee0d40edd7 | ||
|
|
de7c665163 | ||
|
|
6ed54da150 | ||
|
|
254113449a | ||
|
|
59a7c03d48 | ||
|
|
e38be22b73 | ||
|
|
e70e03b902 | ||
|
|
06977b1cad | ||
|
|
431200b658 | ||
|
|
b2244ed294 | ||
|
|
8c8027ca5e | ||
|
|
3bfad238e0 | ||
|
|
0360e00602 | ||
|
|
a4a037fd0d | ||
|
|
f85ed1782a | ||
|
|
0785bd016e | ||
|
|
2f8b810731 | ||
|
|
069c9ac99f | ||
|
|
c189d16129 | ||
|
|
527c0da77d | ||
|
|
e9b7f4d02f | ||
|
|
5316967904 | ||
|
|
9bcd556d04 | ||
|
|
cada811465 | ||
|
|
005d07719f | ||
|
|
85ce0c2dd7 | ||
|
|
2ae6687d91 | ||
|
|
b72743f639 | ||
|
|
7361e3cc64 | ||
|
|
e9c16dee9c | ||
|
|
b94f49e974 | ||
|
|
afa59796ba | ||
|
|
dcc76b0fe3 | ||
|
|
cad1a49514 | ||
|
|
3573f521f4 | ||
|
|
50a4e3d5cd | ||
|
|
134076efed | ||
|
|
ac1a6baa7e | ||
|
|
c5653a809b | ||
|
|
73e3a39ac0 | ||
|
|
052ce245ab | ||
|
|
09ffc3c5e5 | ||
|
|
069568cbfd | ||
|
|
2e37965b56 | ||
|
|
7d43ebed9f | ||
|
|
f52d19b0b5 | ||
|
|
e37ec669e6 | ||
|
|
7f9d41036e | ||
|
|
b728988179 | ||
|
|
6f6cb2c8de | ||
|
|
a203f845e6 | ||
|
|
29a12bb38d | ||
|
|
eb6dc66a73 | ||
|
|
382b8f2372 | ||
|
|
a2dcb20649 | ||
|
|
133f2bfd95 | ||
|
|
75fc2c0b2d | ||
|
|
babb08cae8 | ||
|
|
6430cce125 | ||
|
|
af9def9c69 | ||
|
|
025d6a6537 | ||
|
|
3c50d9ef20 | ||
|
|
fe338e3d63 | ||
|
|
52140feca0 | ||
|
|
de31bdcfd4 | ||
|
|
13dac82ec7 | ||
|
|
7c6712734e | ||
|
|
cdfc4c408a | ||
|
|
33744e7f7a | ||
|
|
d64377d656 | ||
|
|
1cba3a84dd | ||
|
|
51a1b5be9c | ||
|
|
d5e8acf0db | ||
|
|
1beb16e925 | ||
|
|
80701500be | ||
|
|
af1ec638a7 | ||
|
|
9018ed043d | ||
|
|
ec5c93e797 | ||
|
|
0fae0b8942 | ||
|
|
697eb0bc7e | ||
|
|
c1fb559423 | ||
|
|
68b9c895d6 | ||
|
|
a87197d49f | ||
|
|
66b748cc27 | ||
|
|
bd8bae209d | ||
|
|
5a1a4c87c2 | ||
|
|
85be37b550 | ||
|
|
31874c5425 | ||
|
|
6ab651c1b3 | ||
|
|
9daf4b179c | ||
|
|
e1bb1a2c4a | ||
|
|
687016834b | ||
|
|
aa2a87ff60 | ||
|
|
c810e0a1d3 | ||
|
|
6ffd6147c3 | ||
|
|
4915a979e2 | ||
|
|
dafd52497e | ||
|
|
eb0a44a5c4 | ||
|
|
003afb1a98 | ||
|
|
24f3c23b16 | ||
|
|
635b924ef2 | ||
|
|
7997cd4908 | ||
|
|
9c9cc9adfb | ||
|
|
c46b2e4d42 | ||
|
|
71a44d2fd1 | ||
|
|
6485bcd146 | ||
|
|
97a525710a | ||
|
|
91861f7442 | ||
|
|
e8f07fa4f1 | ||
|
|
a64b1d437a | ||
|
|
1411e2a728 | ||
|
|
3d7b848e77 | ||
|
|
9722b78fad | ||
|
|
0eebc4312f | ||
|
|
7df88536b3 | ||
|
|
23fdb17340 | ||
|
|
7e5ae68247 | ||
|
|
1532ffa9b6 | ||
|
|
424afdc178 | ||
|
|
c1502dfc36 | ||
|
|
b389cf8b5c | ||
|
|
fdb4838363 | ||
|
|
78ad53fb9b | ||
|
|
6a3303dffa | ||
|
|
36c2bb2dbb | ||
|
|
d7770c5705 | ||
|
|
ab61fd3857 | ||
|
|
e35dd00024 | ||
|
|
abca49aae7 | ||
|
|
8e5edb641f | ||
|
|
42bd6f720c | ||
|
|
6e7e027bed | ||
|
|
c6901a5311 | ||
|
|
8a03b8c386 | ||
|
|
c06f72b066 | ||
|
|
c039cdc2e8 | ||
|
|
cac335b012 | ||
|
|
55e9dd7299 | ||
|
|
946295bd47 | ||
|
|
c44670caf1 | ||
|
|
97417d3768 | ||
|
|
17e5c8f698 | ||
|
|
a115a855ba | ||
|
|
d387c91b97 | ||
|
|
0ba420a631 | ||
|
|
cfab3924db | ||
|
|
1f22f5920c | ||
|
|
86a034f052 | ||
|
|
e319be2fcf | ||
|
|
0828d2b0b5 | ||
|
|
5579549045 | ||
|
|
c910190c78 | ||
|
|
c5b69f91fa | ||
|
|
2d59b39d2b | ||
|
|
2e5d8cbeab | ||
|
|
5e9e0b0604 | ||
|
|
f11cfe2e23 | ||
|
|
80f2fc1cc2 | ||
|
|
86bca46230 | ||
|
|
69fc5c3a8a | ||
|
|
6a534c393d | ||
|
|
6f124ebfb8 | ||
|
|
fda4275fb0 | ||
|
|
4d2c899715 | ||
|
|
2ebd366e43 | ||
|
|
81ba2581d2 | ||
|
|
a77beea55a | ||
|
|
8792f91a61 | ||
|
|
d13469ed75 | ||
|
|
4183b3a644 | ||
|
|
f1e3fb6696 | ||
|
|
c555878b0e | ||
|
|
bd5b9aef46 | ||
|
|
215be0f23b | ||
|
|
2eefb1d959 | ||
|
|
2ebf1c4bba | ||
|
|
3d40b48cd7 | ||
|
|
418d6d4001 | ||
|
|
49cf05089e | ||
|
|
083276d636 | ||
|
|
c32aa15559 | ||
|
|
9b588e7d54 | ||
|
|
685a83a649 | ||
|
|
5b5f8521ac | ||
|
|
37150c5d59 | ||
|
|
2772371d50 | ||
|
|
6345ab5a5f | ||
|
|
f30b502353 | ||
|
|
7d744fa50e | ||
|
|
19c9ee414d | ||
|
|
a7c2881ee5 | ||
|
|
015c2ddf28 | ||
|
|
2f89831d5a | ||
|
|
31c8529c96 | ||
|
|
d21d0d1222 | ||
|
|
f7f3a69639 | ||
|
|
7e2b572de8 | ||
|
|
00bc0cc54d | ||
|
|
482736d633 | ||
|
|
1a3f6402c4 | ||
|
|
3f14529b52 | ||
|
|
9e149a1204 | ||
|
|
add31d048b | ||
|
|
1533869bbf | ||
|
|
83c5457f37 | ||
|
|
9853a61a74 | ||
|
|
32f4c1a3b3 | ||
|
|
43c4c29266 | ||
|
|
c767bd8ea4 | ||
|
|
670ea453dc | ||
|
|
a1272159d0 | ||
|
|
73a6797833 | ||
|
|
c1a78d5566 | ||
|
|
3403c1c221 | ||
|
|
0186494bf8 | ||
|
|
7b2f02651c | ||
|
|
a9b8576de2 | ||
|
|
6f352c35bd | ||
|
|
bf47ba396e | ||
|
|
76c69f1e56 | ||
|
|
c4a451c86d | ||
|
|
33b6449064 | ||
|
|
581bcdfd16 | ||
|
|
84ac2ed656 | ||
|
|
9bd2d834d4 | ||
|
|
6e2779d244 | ||
|
|
1fc09990a3 | ||
|
|
524c2c3c0b | ||
|
|
377b5807f9 | ||
|
|
099238c893 | ||
|
|
d773dd3c9a | ||
|
|
0d20602d81 | ||
|
|
cc4d8b840a | ||
|
|
692007dd7f | ||
|
|
8a5196b4c2 | ||
|
|
95c1505963 | ||
|
|
dc79eaa7ee | ||
|
|
42aaf9654c | ||
|
|
ddf83985cd | ||
|
|
ef6d57380a | ||
|
|
6fd418735c | ||
|
|
cadcc5633e | ||
|
|
e108570dcf | ||
|
|
6deb56d2ec | ||
|
|
5f11229638 | ||
|
|
675c719e29 | ||
|
|
c269e2ba9b | ||
|
|
04cc38884f | ||
|
|
a72f2a9d5c | ||
|
|
42535640b0 | ||
|
|
f5c017b582 | ||
|
|
b1316120b0 | ||
|
|
947a2e8724 | ||
|
|
0a88455cbf | ||
|
|
1eacb0738d | ||
|
|
07182f6e5b | ||
|
|
c297a81498 | ||
|
|
3a95ae3206 | ||
|
|
367cdaf712 | ||
|
|
2843fd0d1d | ||
|
|
ac9b2029a5 | ||
|
|
e5a65f61c1 | ||
|
|
14316764fe | ||
|
|
2bf8a868e7 | ||
|
|
f1c608de72 | ||
|
|
5de782aeb9 | ||
|
|
1b5e8f0e6a | ||
|
|
42742eca95 | ||
|
|
039864fd90 | ||
|
|
248642a84a | ||
|
|
e46f5b2dc4 | ||
|
|
0341e918f5 | ||
|
|
e124fb26ed | ||
|
|
b8e7532d82 | ||
|
|
92a7f356a7 | ||
|
|
e89270098e | ||
|
|
d757a500c2 | ||
|
|
dc1bea83e7 | ||
|
|
5ee4ca4537 | ||
|
|
95a7de1c04 | ||
|
|
a69e35ea88 | ||
|
|
a593d56002 | ||
|
|
ae9c236a47 | ||
|
|
a717103397 | ||
|
|
8a57124336 | ||
|
|
c55e438328 | ||
|
|
2980228bf6 | ||
|
|
dbb14c55e7 | ||
|
|
e323d1ae71 | ||
|
|
46bb2ba055 | ||
|
|
d7b707a0d9 | ||
|
|
95b0712aef | ||
|
|
18ee36d132 | ||
|
|
130f9932f5 | ||
|
|
ea557bd3cb | ||
|
|
6b73aa9963 | ||
|
|
ce99a5ecb6 | ||
|
|
f3c7678dc0 | ||
|
|
6be4298256 | ||
|
|
e410338511 | ||
|
|
b2221d1baf | ||
|
|
e43cdbebf6 | ||
|
|
0fabe9b059 | ||
|
|
565d80c450 | ||
|
|
76208bd5ac | ||
|
|
fff375d793 | ||
|
|
1672519a02 | ||
|
|
3735f657a1 | ||
|
|
1466a6e28b | ||
|
|
f3f705f414 | ||
|
|
38be92b288 | ||
|
|
14df7837b7 | ||
|
|
bf3aea7ace | ||
|
|
e425e996a7 | ||
|
|
f581536a9e | ||
|
|
26625c0056 | ||
|
|
dd76913297 | ||
|
|
28dfabf992 | ||
|
|
b86d1d58f3 | ||
|
|
8c00b9b2c9 | ||
|
|
de1e230cda | ||
|
|
b71da6b123 | ||
|
|
29b23c1f1c | ||
|
|
bbab3b7a10 | ||
|
|
cf5bffca2f | ||
|
|
89f6dd735f | ||
|
|
3d9d5c345e | ||
|
|
1f57013c99 | ||
|
|
cc15ded788 | ||
|
|
98134c8427 | ||
|
|
367e5756d8 | ||
|
|
820a7a6aaf | ||
|
|
2522216897 | ||
|
|
38323dec6d | ||
|
|
3b4778aa39 | ||
|
|
b0e20e7b60 | ||
|
|
ff061f9470 | ||
|
|
eaa614a95d | ||
|
|
d5d71c2684 | ||
|
|
468fa3dc39 | ||
|
|
200019a48e | ||
|
|
a83f042c60 | ||
|
|
6c4a574775 | ||
|
|
13ac896773 | ||
|
|
2eec0c38ea | ||
|
|
f3c002b6a5 | ||
|
|
971549189b | ||
|
|
5a91342ead | ||
|
|
0d4c61725c | ||
|
|
614b5df479 | ||
|
|
31f33152bc | ||
|
|
61ef8c9240 | ||
|
|
71d7e83357 | ||
|
|
7fa17b48d1 | ||
|
|
07df2fef88 | ||
|
|
268d127a7e | ||
|
|
2f68eddc55 | ||
|
|
976355ea41 | ||
|
|
8788678c62 | ||
|
|
49daa1180c | ||
|
|
fb4c6ae9b4 | ||
|
|
e89ffee0aa | ||
|
|
ecc1e4d5b7 | ||
|
|
eecf74fa68 | ||
|
|
d844f7d063 | ||
|
|
1c8d36a84c | ||
|
|
7d2b7a94fe | ||
|
|
90185097df | ||
|
|
153c4d7278 | ||
|
|
cb151cc1a8 | ||
|
|
a8e541f0d2 | ||
|
|
d116f69397 | ||
|
|
2be2fab7d1 | ||
|
|
f723d5dec7 | ||
|
|
3c8dedeb9d | ||
|
|
bddc8dd04c | ||
|
|
9840281fac | ||
|
|
5529714c4a | ||
|
|
156d42a628 | ||
|
|
b59f54c2b2 | ||
|
|
c9c8fd9666 | ||
|
|
46ff43598d | ||
|
|
9eb35675d7 | ||
|
|
af0a89a540 | ||
|
|
1d83fc7af7 | ||
|
|
2facf96233 | ||
|
|
4f271e31e4 | ||
|
|
0430994cc2 | ||
|
|
b7e03de184 | ||
|
|
6c333b6100 | ||
|
|
9a2a002b29 | ||
|
|
632c382b43 | ||
|
|
5c226ce7b9 | ||
|
|
a737fc7380 | ||
|
|
0b3755ac9c | ||
|
|
aa4294228f | ||
|
|
279eb14b03 | ||
|
|
590967646e | ||
|
|
646dda6122 | ||
|
|
f11de95a54 | ||
|
|
aa22ac5b65 | ||
|
|
fa8258f29c | ||
|
|
b8f215ad88 | ||
|
|
23f67bd7a3 | ||
|
|
42d4406d1c | ||
|
|
940d88846b | ||
|
|
8a511b140e | ||
|
|
0236239fbb | ||
|
|
a95e9a627a | ||
|
|
669a29fce3 | ||
|
|
c3de6d02f5 | ||
|
|
0b1456c846 | ||
|
|
fdab74e2e7 | ||
|
|
15b03d1b58 | ||
|
|
f62a943b5a | ||
|
|
25633a6136 | ||
|
|
00379c004a | ||
|
|
eb2ac93697 | ||
|
|
2d6ed04f24 | ||
|
|
7df2f66742 | ||
|
|
bb431a3ab2 | ||
|
|
b0d14a1c84 | ||
|
|
f084c24891 | ||
|
|
50534bb2bf | ||
|
|
00ef954d98 | ||
|
|
6a485beed6 | ||
|
|
4eadffae42 | ||
|
|
8d64450519 | ||
|
|
2f9475ee12 | ||
|
|
199796a57a | ||
|
|
97b622f024 | ||
|
|
1ecf0bb87c | ||
|
|
3ace527e12 | ||
|
|
abb9a9f498 | ||
|
|
d99c14e079 | ||
|
|
cfce4bf244 | ||
|
|
dd1f49d75d | ||
|
|
e5dbccbaba | ||
|
|
6f38ac2beb | ||
|
|
ae4221b560 | ||
|
|
b1dae4c7e4 | ||
|
|
710ff6c591 | ||
|
|
a06fbc12fd | ||
|
|
8b8ce2dc48 | ||
|
|
f25b71ab89 | ||
|
|
1191502013 | ||
|
|
b576b15460 | ||
|
|
5d3eb2e0dc | ||
|
|
6a86852930 | ||
|
|
b441530fb7 | ||
|
|
4ca6cf6c9a | ||
|
|
6f435c14c9 | ||
|
|
7d2f5fe51f | ||
|
|
16c374870f | ||
|
|
f50bf20edb | ||
|
|
b8b76143ce | ||
|
|
7df7717190 | ||
|
|
0d94fd0c60 | ||
|
|
863b091f8c | ||
|
|
1c605930c8 | ||
|
|
af680ed1d0 | ||
|
|
af36e57afa | ||
|
|
0b8ef8e981 | ||
|
|
b13f138dcd | ||
|
|
489c07a569 | ||
|
|
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 | ||
|
|
530724013e | ||
|
|
e8d6b5cf83 |
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -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.
|
||||
64
BUILD
64
BUILD
@@ -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"],
|
||||
)
|
||||
7
CONTRIBUTING.md
Normal file
7
CONTRIBUTING.md
Normal file
@@ -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
|
||||
496
Godeps/Godeps.json
generated
496
Godeps/Godeps.json
generated
File diff suppressed because it is too large
Load Diff
2
Godeps/OWNERS
generated
Normal file
2
Godeps/OWNERS
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
approvers:
|
||||
- dep-approvers
|
||||
18
README.md
18
README.md
@@ -29,6 +29,8 @@ This is an example of how to build a kube-like controller with a single type.
|
||||
|
||||
## Running
|
||||
|
||||
**Prerequisite**: Since the sample-controller uses `apps/v1` deployments, the Kubernetes cluster version should be greater than 1.9.
|
||||
|
||||
```sh
|
||||
# assumes you have a working kubeconfig, not required if operating in-cluster
|
||||
$ go run *.go -kubeconfig=$HOME/.kube/config
|
||||
@@ -73,6 +75,22 @@ 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. If you are using v1.8, enable the feature using
|
||||
the `CustomResourceValidation` feature gate on the [kube-apiserver](https://kubernetes.io/docs/admin/kube-apiserver):
|
||||
|
||||
```sh
|
||||
--feature-gates=CustomResourceValidation=true
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
The schema in the [example CRD](./artifacts/examples/crd.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.
|
||||
|
||||
## Cleanup
|
||||
|
||||
You can clean up the created CustomResourceDefinition with:
|
||||
|
||||
@@ -9,3 +9,12 @@ spec:
|
||||
kind: Foo
|
||||
plural: foos
|
||||
scope: Namespaced
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
spec:
|
||||
properties:
|
||||
replicas:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
|
||||
3
code-of-conduct.md
Normal file
3
code-of-conduct.md
Normal file
@@ -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)
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
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/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
@@ -93,7 +93,7 @@ func NewController(
|
||||
|
||||
// obtain references to shared index informers for the Deployment and Foo
|
||||
// types.
|
||||
deploymentInformer := kubeInformerFactory.Apps().V1beta2().Deployments()
|
||||
deploymentInformer := kubeInformerFactory.Apps().V1().Deployments()
|
||||
fooInformer := sampleInformerFactory.Samplecontroller().V1alpha1().Foos()
|
||||
|
||||
// Create event broadcaster
|
||||
@@ -134,8 +134,8 @@ func NewController(
|
||||
deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: controller.handleObject,
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
newDepl := new.(*appsv1beta2.Deployment)
|
||||
oldDepl := old.(*appsv1beta2.Deployment)
|
||||
newDepl := new.(*appsv1.Deployment)
|
||||
oldDepl := old.(*appsv1.Deployment)
|
||||
if newDepl.ResourceVersion == oldDepl.ResourceVersion {
|
||||
// Periodic resync will send update events for all known Deployments.
|
||||
// Two different versions of the same Deployment will always have different RVs.
|
||||
@@ -277,7 +277,7 @@ func (c *Controller) syncHandler(key string) error {
|
||||
deployment, err := c.deploymentsLister.Deployments(foo.Namespace).Get(deploymentName)
|
||||
// If the resource doesn't exist, we'll create it
|
||||
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
|
||||
@@ -299,8 +299,8 @@ func (c *Controller) syncHandler(key string) error {
|
||||
// number does not equal the current desired replicas on the Deployment, we
|
||||
// should update the Deployment resource.
|
||||
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)
|
||||
deployment, err = c.kubeclientset.AppsV1beta2().Deployments(foo.Namespace).Update(newDeployment(foo))
|
||||
glog.V(4).Infof("Foo %s replicas: %d, deployment replicas: %d", name, *foo.Spec.Replicas, *deployment.Spec.Replicas)
|
||||
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
|
||||
@@ -321,7 +321,7 @@ func (c *Controller) syncHandler(key string) error {
|
||||
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.
|
||||
// You can use DeepCopy() to make a deep copy of original object and modify this copy
|
||||
// Or create a copy manually for better performance
|
||||
@@ -391,12 +391,12 @@ func (c *Controller) handleObject(obj interface{}) {
|
||||
// newDeployment creates a new Deployment for a Foo resource. It also sets
|
||||
// the appropriate OwnerReferences on the resource so handleObject can discover
|
||||
// the Foo resource that 'owns' it.
|
||||
func newDeployment(foo *samplev1alpha1.Foo) *appsv1beta2.Deployment {
|
||||
func newDeployment(foo *samplev1alpha1.Foo) *appsv1.Deployment {
|
||||
labels := map[string]string{
|
||||
"app": "nginx",
|
||||
"controller": foo.Name,
|
||||
}
|
||||
return &appsv1beta2.Deployment{
|
||||
return &appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: foo.Spec.DeploymentName,
|
||||
Namespace: foo.Namespace,
|
||||
@@ -408,7 +408,7 @@ func newDeployment(foo *samplev1alpha1.Foo) *appsv1beta2.Deployment {
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: appsv1beta2.DeploymentSpec{
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: foo.Spec.Replicas,
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: labels,
|
||||
|
||||
16
hack/boilerplate.go.txt
Normal file
16
hack/boilerplate.go.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Copyright YEAR 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.
|
||||
*/
|
||||
|
||||
@@ -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" \
|
||||
k8s.io/sample-controller/pkg/client k8s.io/sample-controller/pkg/apis \
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
@@ -47,5 +48,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&Foo{},
|
||||
&FooList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
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
|
||||
|
||||
@@ -48,9 +48,8 @@ func (in *Foo) DeepCopy() *Foo {
|
||||
func (in *Foo) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return 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 {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return 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 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
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 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
@@ -41,7 +43,15 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
|
||||
fakePtr := testing.Fake{}
|
||||
fakePtr.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))
|
||||
fakePtr.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}}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
@@ -38,7 +40,7 @@ func init() {
|
||||
//
|
||||
// import (
|
||||
// "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"
|
||||
// )
|
||||
//
|
||||
@@ -49,5 +51,4 @@ func init() {
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.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 2019 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.
|
||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
@@ -38,7 +40,7 @@ func init() {
|
||||
//
|
||||
// import (
|
||||
// "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"
|
||||
// )
|
||||
//
|
||||
@@ -49,5 +51,4 @@ func init() {
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.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 2019 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.
|
||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
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 2019 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.
|
||||
@@ -14,5 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type FooExpansion interface{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
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 2019 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.
|
||||
@@ -14,11 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -26,9 +30,6 @@ import (
|
||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
||||
samplecontroller "k8s.io/sample-controller/pkg/client/informers/externalversions/samplecontroller"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
)
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
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 2019 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.
|
||||
@@ -14,16 +14,17 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||
time "time"
|
||||
)
|
||||
|
||||
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 2019 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.
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
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 2019 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.
|
||||
@@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
@@ -27,7 +29,6 @@ import (
|
||||
versioned "k8s.io/sample-controller/pkg/client/clientset/versioned"
|
||||
internalinterfaces "k8s.io/sample-controller/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "k8s.io/sample-controller/pkg/client/listers/samplecontroller/v1alpha1"
|
||||
time "time"
|
||||
)
|
||||
|
||||
// FooInformer provides access to a shared informer and lister for
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by informer-gen
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
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 2019 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.
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by lister-gen
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
Copyright 2019 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.
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by lister-gen
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
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
vendor/github.com/go-openapi/spec/expander.go
generated
vendored
900
vendor/github.com/go-openapi/spec/expander.go
generated
vendored
@@ -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
|
||||
}
|
||||
1
vendor/github.com/google/btree/.travis.yml
generated
vendored
1
vendor/github.com/google/btree/.travis.yml
generated
vendored
@@ -1 +0,0 @@
|
||||
language: go
|
||||
12
vendor/github.com/google/btree/README.md
generated
vendored
12
vendor/github.com/google/btree/README.md
generated
vendored
@@ -1,12 +0,0 @@
|
||||
# BTree implementation for Go
|
||||
|
||||

|
||||
|
||||
This package provides an in-memory B-Tree implementation for Go, useful as
|
||||
an ordered, mutable data structure.
|
||||
|
||||
The API is based off of the wonderful
|
||||
http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to
|
||||
act as a drop-in replacement for gollrb trees.
|
||||
|
||||
See http://godoc.org/github.com/google/btree for documentation.
|
||||
649
vendor/github.com/google/btree/btree.go
generated
vendored
649
vendor/github.com/google/btree/btree.go
generated
vendored
@@ -1,649 +0,0 @@
|
||||
// Copyright 2014 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package btree implements in-memory B-Trees of arbitrary degree.
|
||||
//
|
||||
// btree implements an in-memory B-Tree for use as an ordered data structure.
|
||||
// It is not meant for persistent storage solutions.
|
||||
//
|
||||
// It has a flatter structure than an equivalent red-black or other binary tree,
|
||||
// which in some cases yields better memory usage and/or performance.
|
||||
// See some discussion on the matter here:
|
||||
// http://google-opensource.blogspot.com/2013/01/c-containers-that-save-memory-and-time.html
|
||||
// Note, though, that this project is in no way related to the C++ B-Tree
|
||||
// implmentation written about there.
|
||||
//
|
||||
// Within this tree, each node contains a slice of items and a (possibly nil)
|
||||
// slice of children. For basic numeric values or raw structs, this can cause
|
||||
// efficiency differences when compared to equivalent C++ template code that
|
||||
// stores values in arrays within the node:
|
||||
// * Due to the overhead of storing values as interfaces (each
|
||||
// value needs to be stored as the value itself, then 2 words for the
|
||||
// interface pointing to that value and its type), resulting in higher
|
||||
// memory use.
|
||||
// * Since interfaces can point to values anywhere in memory, values are
|
||||
// most likely not stored in contiguous blocks, resulting in a higher
|
||||
// number of cache misses.
|
||||
// These issues don't tend to matter, though, when working with strings or other
|
||||
// heap-allocated structures, since C++-equivalent structures also must store
|
||||
// pointers and also distribute their values across the heap.
|
||||
//
|
||||
// This implementation is designed to be a drop-in replacement to gollrb.LLRB
|
||||
// trees, (http://github.com/petar/gollrb), an excellent and probably the most
|
||||
// widely used ordered tree implementation in the Go ecosystem currently.
|
||||
// Its functions, therefore, exactly mirror those of
|
||||
// llrb.LLRB where possible. Unlike gollrb, though, we currently don't
|
||||
// support storing multiple equivalent values or backwards iteration.
|
||||
package btree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Item represents a single object in the tree.
|
||||
type Item interface {
|
||||
// Less tests whether the current item is less than the given argument.
|
||||
//
|
||||
// This must provide a strict weak ordering.
|
||||
// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only
|
||||
// hold one of either a or b in the tree).
|
||||
Less(than Item) bool
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultFreeListSize = 32
|
||||
)
|
||||
|
||||
// FreeList represents a free list of btree nodes. By default each
|
||||
// BTree has its own FreeList, but multiple BTrees can share the same
|
||||
// FreeList.
|
||||
// Two Btrees using the same freelist are not safe for concurrent write access.
|
||||
type FreeList struct {
|
||||
freelist []*node
|
||||
}
|
||||
|
||||
// NewFreeList creates a new free list.
|
||||
// size is the maximum size of the returned free list.
|
||||
func NewFreeList(size int) *FreeList {
|
||||
return &FreeList{freelist: make([]*node, 0, size)}
|
||||
}
|
||||
|
||||
func (f *FreeList) newNode() (n *node) {
|
||||
index := len(f.freelist) - 1
|
||||
if index < 0 {
|
||||
return new(node)
|
||||
}
|
||||
f.freelist, n = f.freelist[:index], f.freelist[index]
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FreeList) freeNode(n *node) {
|
||||
if len(f.freelist) < cap(f.freelist) {
|
||||
f.freelist = append(f.freelist, n)
|
||||
}
|
||||
}
|
||||
|
||||
// ItemIterator allows callers of Ascend* to iterate in-order over portions of
|
||||
// the tree. When this function returns false, iteration will stop and the
|
||||
// associated Ascend* function will immediately return.
|
||||
type ItemIterator func(i Item) bool
|
||||
|
||||
// New creates a new B-Tree with the given degree.
|
||||
//
|
||||
// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items
|
||||
// and 2-4 children).
|
||||
func New(degree int) *BTree {
|
||||
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
|
||||
}
|
||||
|
||||
// NewWithFreeList creates a new B-Tree that uses the given node free list.
|
||||
func NewWithFreeList(degree int, f *FreeList) *BTree {
|
||||
if degree <= 1 {
|
||||
panic("bad degree")
|
||||
}
|
||||
return &BTree{
|
||||
degree: degree,
|
||||
freelist: f,
|
||||
}
|
||||
}
|
||||
|
||||
// items stores items in a node.
|
||||
type items []Item
|
||||
|
||||
// insertAt inserts a value into the given index, pushing all subsequent values
|
||||
// forward.
|
||||
func (s *items) insertAt(index int, item Item) {
|
||||
*s = append(*s, nil)
|
||||
if index < len(*s) {
|
||||
copy((*s)[index+1:], (*s)[index:])
|
||||
}
|
||||
(*s)[index] = item
|
||||
}
|
||||
|
||||
// removeAt removes a value at a given index, pulling all subsequent values
|
||||
// back.
|
||||
func (s *items) removeAt(index int) Item {
|
||||
item := (*s)[index]
|
||||
(*s)[index] = nil
|
||||
copy((*s)[index:], (*s)[index+1:])
|
||||
*s = (*s)[:len(*s)-1]
|
||||
return item
|
||||
}
|
||||
|
||||
// pop removes and returns the last element in the list.
|
||||
func (s *items) pop() (out Item) {
|
||||
index := len(*s) - 1
|
||||
out = (*s)[index]
|
||||
(*s)[index] = nil
|
||||
*s = (*s)[:index]
|
||||
return
|
||||
}
|
||||
|
||||
// find returns the index where the given item should be inserted into this
|
||||
// list. 'found' is true if the item already exists in the list at the given
|
||||
// index.
|
||||
func (s items) find(item Item) (index int, found bool) {
|
||||
i := sort.Search(len(s), func(i int) bool {
|
||||
return item.Less(s[i])
|
||||
})
|
||||
if i > 0 && !s[i-1].Less(item) {
|
||||
return i - 1, true
|
||||
}
|
||||
return i, false
|
||||
}
|
||||
|
||||
// children stores child nodes in a node.
|
||||
type children []*node
|
||||
|
||||
// insertAt inserts a value into the given index, pushing all subsequent values
|
||||
// forward.
|
||||
func (s *children) insertAt(index int, n *node) {
|
||||
*s = append(*s, nil)
|
||||
if index < len(*s) {
|
||||
copy((*s)[index+1:], (*s)[index:])
|
||||
}
|
||||
(*s)[index] = n
|
||||
}
|
||||
|
||||
// removeAt removes a value at a given index, pulling all subsequent values
|
||||
// back.
|
||||
func (s *children) removeAt(index int) *node {
|
||||
n := (*s)[index]
|
||||
(*s)[index] = nil
|
||||
copy((*s)[index:], (*s)[index+1:])
|
||||
*s = (*s)[:len(*s)-1]
|
||||
return n
|
||||
}
|
||||
|
||||
// pop removes and returns the last element in the list.
|
||||
func (s *children) pop() (out *node) {
|
||||
index := len(*s) - 1
|
||||
out = (*s)[index]
|
||||
(*s)[index] = nil
|
||||
*s = (*s)[:index]
|
||||
return
|
||||
}
|
||||
|
||||
// node is an internal node in a tree.
|
||||
//
|
||||
// It must at all times maintain the invariant that either
|
||||
// * len(children) == 0, len(items) unconstrained
|
||||
// * len(children) == len(items) + 1
|
||||
type node struct {
|
||||
items items
|
||||
children children
|
||||
t *BTree
|
||||
}
|
||||
|
||||
// split splits the given node at the given index. The current node shrinks,
|
||||
// and this function returns the item that existed at that index and a new node
|
||||
// containing all items/children after it.
|
||||
func (n *node) split(i int) (Item, *node) {
|
||||
item := n.items[i]
|
||||
next := n.t.newNode()
|
||||
next.items = append(next.items, n.items[i+1:]...)
|
||||
n.items = n.items[:i]
|
||||
if len(n.children) > 0 {
|
||||
next.children = append(next.children, n.children[i+1:]...)
|
||||
n.children = n.children[:i+1]
|
||||
}
|
||||
return item, next
|
||||
}
|
||||
|
||||
// maybeSplitChild checks if a child should be split, and if so splits it.
|
||||
// Returns whether or not a split occurred.
|
||||
func (n *node) maybeSplitChild(i, maxItems int) bool {
|
||||
if len(n.children[i].items) < maxItems {
|
||||
return false
|
||||
}
|
||||
first := n.children[i]
|
||||
item, second := first.split(maxItems / 2)
|
||||
n.items.insertAt(i, item)
|
||||
n.children.insertAt(i+1, second)
|
||||
return true
|
||||
}
|
||||
|
||||
// insert inserts an item into the subtree rooted at this node, making sure
|
||||
// no nodes in the subtree exceed maxItems items. Should an equivalent item be
|
||||
// be found/replaced by insert, it will be returned.
|
||||
func (n *node) insert(item Item, maxItems int) Item {
|
||||
i, found := n.items.find(item)
|
||||
if found {
|
||||
out := n.items[i]
|
||||
n.items[i] = item
|
||||
return out
|
||||
}
|
||||
if len(n.children) == 0 {
|
||||
n.items.insertAt(i, item)
|
||||
return nil
|
||||
}
|
||||
if n.maybeSplitChild(i, maxItems) {
|
||||
inTree := n.items[i]
|
||||
switch {
|
||||
case item.Less(inTree):
|
||||
// no change, we want first split node
|
||||
case inTree.Less(item):
|
||||
i++ // we want second split node
|
||||
default:
|
||||
out := n.items[i]
|
||||
n.items[i] = item
|
||||
return out
|
||||
}
|
||||
}
|
||||
return n.children[i].insert(item, maxItems)
|
||||
}
|
||||
|
||||
// get finds the given key in the subtree and returns it.
|
||||
func (n *node) get(key Item) Item {
|
||||
i, found := n.items.find(key)
|
||||
if found {
|
||||
return n.items[i]
|
||||
} else if len(n.children) > 0 {
|
||||
return n.children[i].get(key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// min returns the first item in the subtree.
|
||||
func min(n *node) Item {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
for len(n.children) > 0 {
|
||||
n = n.children[0]
|
||||
}
|
||||
if len(n.items) == 0 {
|
||||
return nil
|
||||
}
|
||||
return n.items[0]
|
||||
}
|
||||
|
||||
// max returns the last item in the subtree.
|
||||
func max(n *node) Item {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
for len(n.children) > 0 {
|
||||
n = n.children[len(n.children)-1]
|
||||
}
|
||||
if len(n.items) == 0 {
|
||||
return nil
|
||||
}
|
||||
return n.items[len(n.items)-1]
|
||||
}
|
||||
|
||||
// toRemove details what item to remove in a node.remove call.
|
||||
type toRemove int
|
||||
|
||||
const (
|
||||
removeItem toRemove = iota // removes the given item
|
||||
removeMin // removes smallest item in the subtree
|
||||
removeMax // removes largest item in the subtree
|
||||
)
|
||||
|
||||
// remove removes an item from the subtree rooted at this node.
|
||||
func (n *node) remove(item Item, minItems int, typ toRemove) Item {
|
||||
var i int
|
||||
var found bool
|
||||
switch typ {
|
||||
case removeMax:
|
||||
if len(n.children) == 0 {
|
||||
return n.items.pop()
|
||||
}
|
||||
i = len(n.items)
|
||||
case removeMin:
|
||||
if len(n.children) == 0 {
|
||||
return n.items.removeAt(0)
|
||||
}
|
||||
i = 0
|
||||
case removeItem:
|
||||
i, found = n.items.find(item)
|
||||
if len(n.children) == 0 {
|
||||
if found {
|
||||
return n.items.removeAt(i)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
panic("invalid type")
|
||||
}
|
||||
// If we get to here, we have children.
|
||||
child := n.children[i]
|
||||
if len(child.items) <= minItems {
|
||||
return n.growChildAndRemove(i, item, minItems, typ)
|
||||
}
|
||||
// Either we had enough items to begin with, or we've done some
|
||||
// merging/stealing, because we've got enough now and we're ready to return
|
||||
// stuff.
|
||||
if found {
|
||||
// The item exists at index 'i', and the child we've selected can give us a
|
||||
// predecessor, since if we've gotten here it's got > minItems items in it.
|
||||
out := n.items[i]
|
||||
// We use our special-case 'remove' call with typ=maxItem to pull the
|
||||
// predecessor of item i (the rightmost leaf of our immediate left child)
|
||||
// and set it into where we pulled the item from.
|
||||
n.items[i] = child.remove(nil, minItems, removeMax)
|
||||
return out
|
||||
}
|
||||
// Final recursive call. Once we're here, we know that the item isn't in this
|
||||
// node and that the child is big enough to remove from.
|
||||
return child.remove(item, minItems, typ)
|
||||
}
|
||||
|
||||
// growChildAndRemove grows child 'i' to make sure it's possible to remove an
|
||||
// item from it while keeping it at minItems, then calls remove to actually
|
||||
// remove it.
|
||||
//
|
||||
// Most documentation says we have to do two sets of special casing:
|
||||
// 1) item is in this node
|
||||
// 2) item is in child
|
||||
// In both cases, we need to handle the two subcases:
|
||||
// A) node has enough values that it can spare one
|
||||
// B) node doesn't have enough values
|
||||
// For the latter, we have to check:
|
||||
// a) left sibling has node to spare
|
||||
// b) right sibling has node to spare
|
||||
// c) we must merge
|
||||
// To simplify our code here, we handle cases #1 and #2 the same:
|
||||
// If a node doesn't have enough items, we make sure it does (using a,b,c).
|
||||
// We then simply redo our remove call, and the second time (regardless of
|
||||
// whether we're in case 1 or 2), we'll have enough items and can guarantee
|
||||
// that we hit case A.
|
||||
func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item {
|
||||
child := n.children[i]
|
||||
if i > 0 && len(n.children[i-1].items) > minItems {
|
||||
// Steal from left child
|
||||
stealFrom := n.children[i-1]
|
||||
stolenItem := stealFrom.items.pop()
|
||||
child.items.insertAt(0, n.items[i-1])
|
||||
n.items[i-1] = stolenItem
|
||||
if len(stealFrom.children) > 0 {
|
||||
child.children.insertAt(0, stealFrom.children.pop())
|
||||
}
|
||||
} else if i < len(n.items) && len(n.children[i+1].items) > minItems {
|
||||
// steal from right child
|
||||
stealFrom := n.children[i+1]
|
||||
stolenItem := stealFrom.items.removeAt(0)
|
||||
child.items = append(child.items, n.items[i])
|
||||
n.items[i] = stolenItem
|
||||
if len(stealFrom.children) > 0 {
|
||||
child.children = append(child.children, stealFrom.children.removeAt(0))
|
||||
}
|
||||
} else {
|
||||
if i >= len(n.items) {
|
||||
i--
|
||||
child = n.children[i]
|
||||
}
|
||||
// merge with right child
|
||||
mergeItem := n.items.removeAt(i)
|
||||
mergeChild := n.children.removeAt(i + 1)
|
||||
child.items = append(child.items, mergeItem)
|
||||
child.items = append(child.items, mergeChild.items...)
|
||||
child.children = append(child.children, mergeChild.children...)
|
||||
n.t.freeNode(mergeChild)
|
||||
}
|
||||
return n.remove(item, minItems, typ)
|
||||
}
|
||||
|
||||
// iterate provides a simple method for iterating over elements in the tree.
|
||||
// It could probably use some work to be extra-efficient (it calls from() a
|
||||
// little more than it should), but it works pretty well for now.
|
||||
//
|
||||
// It requires that 'from' and 'to' both return true for values we should hit
|
||||
// with the iterator. It should also be the case that 'from' returns true for
|
||||
// values less than or equal to values 'to' returns true for, and 'to'
|
||||
// returns true for values greater than or equal to those that 'from'
|
||||
// does.
|
||||
func (n *node) iterate(from, to func(Item) bool, iter ItemIterator) bool {
|
||||
for i, item := range n.items {
|
||||
if !from(item) {
|
||||
continue
|
||||
}
|
||||
if len(n.children) > 0 && !n.children[i].iterate(from, to, iter) {
|
||||
return false
|
||||
}
|
||||
if !to(item) {
|
||||
return false
|
||||
}
|
||||
if !iter(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if len(n.children) > 0 {
|
||||
return n.children[len(n.children)-1].iterate(from, to, iter)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Used for testing/debugging purposes.
|
||||
func (n *node) print(w io.Writer, level int) {
|
||||
fmt.Fprintf(w, "%sNODE:%v\n", strings.Repeat(" ", level), n.items)
|
||||
for _, c := range n.children {
|
||||
c.print(w, level+1)
|
||||
}
|
||||
}
|
||||
|
||||
// BTree is an implementation of a B-Tree.
|
||||
//
|
||||
// BTree stores Item instances in an ordered structure, allowing easy insertion,
|
||||
// removal, and iteration.
|
||||
//
|
||||
// Write operations are not safe for concurrent mutation by multiple
|
||||
// goroutines, but Read operations are.
|
||||
type BTree struct {
|
||||
degree int
|
||||
length int
|
||||
root *node
|
||||
freelist *FreeList
|
||||
}
|
||||
|
||||
// maxItems returns the max number of items to allow per node.
|
||||
func (t *BTree) maxItems() int {
|
||||
return t.degree*2 - 1
|
||||
}
|
||||
|
||||
// minItems returns the min number of items to allow per node (ignored for the
|
||||
// root node).
|
||||
func (t *BTree) minItems() int {
|
||||
return t.degree - 1
|
||||
}
|
||||
|
||||
func (t *BTree) newNode() (n *node) {
|
||||
n = t.freelist.newNode()
|
||||
n.t = t
|
||||
return
|
||||
}
|
||||
|
||||
func (t *BTree) freeNode(n *node) {
|
||||
for i := range n.items {
|
||||
n.items[i] = nil // clear to allow GC
|
||||
}
|
||||
n.items = n.items[:0]
|
||||
for i := range n.children {
|
||||
n.children[i] = nil // clear to allow GC
|
||||
}
|
||||
n.children = n.children[:0]
|
||||
n.t = nil // clear to allow GC
|
||||
t.freelist.freeNode(n)
|
||||
}
|
||||
|
||||
// ReplaceOrInsert adds the given item to the tree. If an item in the tree
|
||||
// already equals the given one, it is removed from the tree and returned.
|
||||
// Otherwise, nil is returned.
|
||||
//
|
||||
// nil cannot be added to the tree (will panic).
|
||||
func (t *BTree) ReplaceOrInsert(item Item) Item {
|
||||
if item == nil {
|
||||
panic("nil item being added to BTree")
|
||||
}
|
||||
if t.root == nil {
|
||||
t.root = t.newNode()
|
||||
t.root.items = append(t.root.items, item)
|
||||
t.length++
|
||||
return nil
|
||||
} else if len(t.root.items) >= t.maxItems() {
|
||||
item2, second := t.root.split(t.maxItems() / 2)
|
||||
oldroot := t.root
|
||||
t.root = t.newNode()
|
||||
t.root.items = append(t.root.items, item2)
|
||||
t.root.children = append(t.root.children, oldroot, second)
|
||||
}
|
||||
out := t.root.insert(item, t.maxItems())
|
||||
if out == nil {
|
||||
t.length++
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Delete removes an item equal to the passed in item from the tree, returning
|
||||
// it. If no such item exists, returns nil.
|
||||
func (t *BTree) Delete(item Item) Item {
|
||||
return t.deleteItem(item, removeItem)
|
||||
}
|
||||
|
||||
// DeleteMin removes the smallest item in the tree and returns it.
|
||||
// If no such item exists, returns nil.
|
||||
func (t *BTree) DeleteMin() Item {
|
||||
return t.deleteItem(nil, removeMin)
|
||||
}
|
||||
|
||||
// DeleteMax removes the largest item in the tree and returns it.
|
||||
// If no such item exists, returns nil.
|
||||
func (t *BTree) DeleteMax() Item {
|
||||
return t.deleteItem(nil, removeMax)
|
||||
}
|
||||
|
||||
func (t *BTree) deleteItem(item Item, typ toRemove) Item {
|
||||
if t.root == nil || len(t.root.items) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := t.root.remove(item, t.minItems(), typ)
|
||||
if len(t.root.items) == 0 && len(t.root.children) > 0 {
|
||||
oldroot := t.root
|
||||
t.root = t.root.children[0]
|
||||
t.freeNode(oldroot)
|
||||
}
|
||||
if out != nil {
|
||||
t.length--
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// AscendRange calls the iterator for every value in the tree within the range
|
||||
// [greaterOrEqual, lessThan), until iterator returns false.
|
||||
func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) {
|
||||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return !a.Less(greaterOrEqual) },
|
||||
func(a Item) bool { return a.Less(lessThan) },
|
||||
iterator)
|
||||
}
|
||||
|
||||
// AscendLessThan calls the iterator for every value in the tree within the range
|
||||
// [first, pivot), until iterator returns false.
|
||||
func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) {
|
||||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return true },
|
||||
func(a Item) bool { return a.Less(pivot) },
|
||||
iterator)
|
||||
}
|
||||
|
||||
// AscendGreaterOrEqual calls the iterator for every value in the tree within
|
||||
// the range [pivot, last], until iterator returns false.
|
||||
func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
|
||||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return !a.Less(pivot) },
|
||||
func(a Item) bool { return true },
|
||||
iterator)
|
||||
}
|
||||
|
||||
// Ascend calls the iterator for every value in the tree within the range
|
||||
// [first, last], until iterator returns false.
|
||||
func (t *BTree) Ascend(iterator ItemIterator) {
|
||||
if t.root == nil {
|
||||
return
|
||||
}
|
||||
t.root.iterate(
|
||||
func(a Item) bool { return true },
|
||||
func(a Item) bool { return true },
|
||||
iterator)
|
||||
}
|
||||
|
||||
// Get looks for the key item in the tree, returning it. It returns nil if
|
||||
// unable to find that item.
|
||||
func (t *BTree) Get(key Item) Item {
|
||||
if t.root == nil {
|
||||
return nil
|
||||
}
|
||||
return t.root.get(key)
|
||||
}
|
||||
|
||||
// Min returns the smallest item in the tree, or nil if the tree is empty.
|
||||
func (t *BTree) Min() Item {
|
||||
return min(t.root)
|
||||
}
|
||||
|
||||
// Max returns the largest item in the tree, or nil if the tree is empty.
|
||||
func (t *BTree) Max() Item {
|
||||
return max(t.root)
|
||||
}
|
||||
|
||||
// Has returns true if the given key is in the tree.
|
||||
func (t *BTree) Has(key Item) bool {
|
||||
return t.Get(key) != nil
|
||||
}
|
||||
|
||||
// Len returns the number of items currently in the tree.
|
||||
func (t *BTree) Len() int {
|
||||
return t.length
|
||||
}
|
||||
|
||||
// Int implements the Item interface for integers.
|
||||
type Int int
|
||||
|
||||
// Less returns true if int(a) < int(b).
|
||||
func (a Int) Less(b Item) bool {
|
||||
return a < b.(Int)
|
||||
}
|
||||
76
vendor/github.com/google/btree/btree_mem.go
generated
vendored
76
vendor/github.com/google/btree/btree_mem.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
// Copyright 2014 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This binary compares memory usage between btree and gollrb.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/google/btree"
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
)
|
||||
|
||||
var (
|
||||
size = flag.Int("size", 1000000, "size of the tree to build")
|
||||
degree = flag.Int("degree", 8, "degree of btree")
|
||||
gollrb = flag.Bool("llrb", false, "use llrb instead of btree")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
vals := rand.Perm(*size)
|
||||
var t, v interface{}
|
||||
v = vals
|
||||
var stats runtime.MemStats
|
||||
for i := 0; i < 10; i++ {
|
||||
runtime.GC()
|
||||
}
|
||||
fmt.Println("-------- BEFORE ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
start := time.Now()
|
||||
if *gollrb {
|
||||
tr := llrb.New()
|
||||
for _, v := range vals {
|
||||
tr.ReplaceOrInsert(llrb.Int(v))
|
||||
}
|
||||
t = tr // keep it around
|
||||
} else {
|
||||
tr := btree.New(*degree)
|
||||
for _, v := range vals {
|
||||
tr.ReplaceOrInsert(btree.Int(v))
|
||||
}
|
||||
t = tr // keep it around
|
||||
}
|
||||
fmt.Printf("%v inserts in %v\n", *size, time.Since(start))
|
||||
fmt.Println("-------- AFTER ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
for i := 0; i < 10; i++ {
|
||||
runtime.GC()
|
||||
}
|
||||
fmt.Println("-------- AFTER GC ----------")
|
||||
runtime.ReadMemStats(&stats)
|
||||
fmt.Printf("%+v\n", stats)
|
||||
if t == v {
|
||||
fmt.Println("to make sure vals and tree aren't GC'd")
|
||||
}
|
||||
}
|
||||
18
vendor/github.com/gregjones/httpcache/.travis.yml
generated
vendored
18
vendor/github.com/gregjones/httpcache/.travis.yml
generated
vendored
@@ -1,18 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- master
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: master
|
||||
fast_finish: true
|
||||
install:
|
||||
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d .)
|
||||
- go tool vet .
|
||||
- go test -v -race ./...
|
||||
7
vendor/github.com/gregjones/httpcache/LICENSE.txt
generated
vendored
7
vendor/github.com/gregjones/httpcache/LICENSE.txt
generated
vendored
@@ -1,7 +0,0 @@
|
||||
Copyright © 2012 Greg Jones (greg.jones@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
24
vendor/github.com/gregjones/httpcache/README.md
generated
vendored
24
vendor/github.com/gregjones/httpcache/README.md
generated
vendored
@@ -1,24 +0,0 @@
|
||||
httpcache
|
||||
=========
|
||||
|
||||
[](https://travis-ci.org/gregjones/httpcache) [](https://godoc.org/github.com/gregjones/httpcache)
|
||||
|
||||
Package httpcache provides a http.RoundTripper implementation that works as a mostly RFC-compliant cache for http responses.
|
||||
|
||||
It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy).
|
||||
|
||||
Cache Backends
|
||||
--------------
|
||||
|
||||
- The built-in 'memory' cache stores responses in an in-memory map.
|
||||
- [`github.com/gregjones/httpcache/diskcache`](https://github.com/gregjones/httpcache/tree/master/diskcache) provides a filesystem-backed cache using the [diskv](https://github.com/peterbourgon/diskv) library.
|
||||
- [`github.com/gregjones/httpcache/memcache`](https://github.com/gregjones/httpcache/tree/master/memcache) provides memcache implementations, for both App Engine and 'normal' memcache servers.
|
||||
- [`sourcegraph.com/sourcegraph/s3cache`](https://sourcegraph.com/github.com/sourcegraph/s3cache) uses Amazon S3 for storage.
|
||||
- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb).
|
||||
- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries.
|
||||
- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
- [MIT License](LICENSE.txt)
|
||||
61
vendor/github.com/gregjones/httpcache/diskcache/diskcache.go
generated
vendored
61
vendor/github.com/gregjones/httpcache/diskcache/diskcache.go
generated
vendored
@@ -1,61 +0,0 @@
|
||||
// Package diskcache provides an implementation of httpcache.Cache that uses the diskv package
|
||||
// to supplement an in-memory map with persistent storage
|
||||
//
|
||||
package diskcache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"github.com/peterbourgon/diskv"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Cache is an implementation of httpcache.Cache that supplements the in-memory map with persistent storage
|
||||
type Cache struct {
|
||||
d *diskv.Diskv
|
||||
}
|
||||
|
||||
// Get returns the response corresponding to key if present
|
||||
func (c *Cache) Get(key string) (resp []byte, ok bool) {
|
||||
key = keyToFilename(key)
|
||||
resp, err := c.d.Read(key)
|
||||
if err != nil {
|
||||
return []byte{}, false
|
||||
}
|
||||
return resp, true
|
||||
}
|
||||
|
||||
// Set saves a response to the cache as key
|
||||
func (c *Cache) Set(key string, resp []byte) {
|
||||
key = keyToFilename(key)
|
||||
c.d.WriteStream(key, bytes.NewReader(resp), true)
|
||||
}
|
||||
|
||||
// Delete removes the response with key from the cache
|
||||
func (c *Cache) Delete(key string) {
|
||||
key = keyToFilename(key)
|
||||
c.d.Erase(key)
|
||||
}
|
||||
|
||||
func keyToFilename(key string) string {
|
||||
h := md5.New()
|
||||
io.WriteString(h, key)
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// New returns a new Cache that will store files in basePath
|
||||
func New(basePath string) *Cache {
|
||||
return &Cache{
|
||||
d: diskv.New(diskv.Options{
|
||||
BasePath: basePath,
|
||||
CacheSizeMax: 100 * 1024 * 1024, // 100MB
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// NewWithDiskv returns a new Cache using the provided Diskv as underlying
|
||||
// storage.
|
||||
func NewWithDiskv(d *diskv.Diskv) *Cache {
|
||||
return &Cache{d}
|
||||
}
|
||||
553
vendor/github.com/gregjones/httpcache/httpcache.go
generated
vendored
553
vendor/github.com/gregjones/httpcache/httpcache.go
generated
vendored
@@ -1,553 +0,0 @@
|
||||
// Package httpcache provides a http.RoundTripper implementation that works as a
|
||||
// mostly RFC-compliant cache for http responses.
|
||||
//
|
||||
// It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client
|
||||
// and not for a shared proxy).
|
||||
//
|
||||
package httpcache
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
stale = iota
|
||||
fresh
|
||||
transparent
|
||||
// XFromCache is the header added to responses that are returned from the cache
|
||||
XFromCache = "X-From-Cache"
|
||||
)
|
||||
|
||||
// A Cache interface is used by the Transport to store and retrieve responses.
|
||||
type Cache interface {
|
||||
// Get returns the []byte representation of a cached response and a bool
|
||||
// set to true if the value isn't empty
|
||||
Get(key string) (responseBytes []byte, ok bool)
|
||||
// Set stores the []byte representation of a response against a key
|
||||
Set(key string, responseBytes []byte)
|
||||
// Delete removes the value associated with the key
|
||||
Delete(key string)
|
||||
}
|
||||
|
||||
// cacheKey returns the cache key for req.
|
||||
func cacheKey(req *http.Request) string {
|
||||
return req.URL.String()
|
||||
}
|
||||
|
||||
// CachedResponse returns the cached http.Response for req if present, and nil
|
||||
// otherwise.
|
||||
func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error) {
|
||||
cachedVal, ok := c.Get(cacheKey(req))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
b := bytes.NewBuffer(cachedVal)
|
||||
return http.ReadResponse(bufio.NewReader(b), req)
|
||||
}
|
||||
|
||||
// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
|
||||
type MemoryCache struct {
|
||||
mu sync.RWMutex
|
||||
items map[string][]byte
|
||||
}
|
||||
|
||||
// Get returns the []byte representation of the response and true if present, false if not
|
||||
func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
|
||||
c.mu.RLock()
|
||||
resp, ok = c.items[key]
|
||||
c.mu.RUnlock()
|
||||
return resp, ok
|
||||
}
|
||||
|
||||
// Set saves response resp to the cache with key
|
||||
func (c *MemoryCache) Set(key string, resp []byte) {
|
||||
c.mu.Lock()
|
||||
c.items[key] = resp
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// Delete removes key from the cache
|
||||
func (c *MemoryCache) Delete(key string) {
|
||||
c.mu.Lock()
|
||||
delete(c.items, key)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// NewMemoryCache returns a new Cache that will store items in an in-memory map
|
||||
func NewMemoryCache() *MemoryCache {
|
||||
c := &MemoryCache{items: map[string][]byte{}}
|
||||
return c
|
||||
}
|
||||
|
||||
// Transport is an implementation of http.RoundTripper that will return values from a cache
|
||||
// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since)
|
||||
// to repeated requests allowing servers to return 304 / Not Modified
|
||||
type Transport struct {
|
||||
// The RoundTripper interface actually used to make requests
|
||||
// If nil, http.DefaultTransport is used
|
||||
Transport http.RoundTripper
|
||||
Cache Cache
|
||||
// If true, responses returned from the cache will be given an extra header, X-From-Cache
|
||||
MarkCachedResponses bool
|
||||
}
|
||||
|
||||
// NewTransport returns a new Transport with the
|
||||
// provided Cache implementation and MarkCachedResponses set to true
|
||||
func NewTransport(c Cache) *Transport {
|
||||
return &Transport{Cache: c, MarkCachedResponses: true}
|
||||
}
|
||||
|
||||
// Client returns an *http.Client that caches responses.
|
||||
func (t *Transport) Client() *http.Client {
|
||||
return &http.Client{Transport: t}
|
||||
}
|
||||
|
||||
// varyMatches will return false unless all of the cached values for the headers listed in Vary
|
||||
// match the new request
|
||||
func varyMatches(cachedResp *http.Response, req *http.Request) bool {
|
||||
for _, header := range headerAllCommaSepValues(cachedResp.Header, "vary") {
|
||||
header = http.CanonicalHeaderKey(header)
|
||||
if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// RoundTrip takes a Request and returns a Response
|
||||
//
|
||||
// If there is a fresh Response already in cache, then it will be returned without connecting to
|
||||
// the server.
|
||||
//
|
||||
// If there is a stale Response, then any validators it contains will be set on the new request
|
||||
// to give the server a chance to respond with NotModified. If this happens, then the cached Response
|
||||
// will be returned.
|
||||
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||
cacheKey := cacheKey(req)
|
||||
cacheable := (req.Method == "GET" || req.Method == "HEAD") && req.Header.Get("range") == ""
|
||||
var cachedResp *http.Response
|
||||
if cacheable {
|
||||
cachedResp, err = CachedResponse(t.Cache, req)
|
||||
} else {
|
||||
// Need to invalidate an existing value
|
||||
t.Cache.Delete(cacheKey)
|
||||
}
|
||||
|
||||
transport := t.Transport
|
||||
if transport == nil {
|
||||
transport = http.DefaultTransport
|
||||
}
|
||||
|
||||
if cacheable && cachedResp != nil && err == nil {
|
||||
if t.MarkCachedResponses {
|
||||
cachedResp.Header.Set(XFromCache, "1")
|
||||
}
|
||||
|
||||
if varyMatches(cachedResp, req) {
|
||||
// Can only use cached value if the new request doesn't Vary significantly
|
||||
freshness := getFreshness(cachedResp.Header, req.Header)
|
||||
if freshness == fresh {
|
||||
return cachedResp, nil
|
||||
}
|
||||
|
||||
if freshness == stale {
|
||||
var req2 *http.Request
|
||||
// Add validators if caller hasn't already done so
|
||||
etag := cachedResp.Header.Get("etag")
|
||||
if etag != "" && req.Header.Get("etag") == "" {
|
||||
req2 = cloneRequest(req)
|
||||
req2.Header.Set("if-none-match", etag)
|
||||
}
|
||||
lastModified := cachedResp.Header.Get("last-modified")
|
||||
if lastModified != "" && req.Header.Get("last-modified") == "" {
|
||||
if req2 == nil {
|
||||
req2 = cloneRequest(req)
|
||||
}
|
||||
req2.Header.Set("if-modified-since", lastModified)
|
||||
}
|
||||
if req2 != nil {
|
||||
req = req2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp, err = transport.RoundTrip(req)
|
||||
if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified {
|
||||
// Replace the 304 response with the one from cache, but update with some new headers
|
||||
endToEndHeaders := getEndToEndHeaders(resp.Header)
|
||||
for _, header := range endToEndHeaders {
|
||||
cachedResp.Header[header] = resp.Header[header]
|
||||
}
|
||||
cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK))
|
||||
cachedResp.StatusCode = http.StatusOK
|
||||
|
||||
resp = cachedResp
|
||||
} else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) &&
|
||||
req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) {
|
||||
// In case of transport failure and stale-if-error activated, returns cached content
|
||||
// when available
|
||||
cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK))
|
||||
cachedResp.StatusCode = http.StatusOK
|
||||
return cachedResp, nil
|
||||
} else {
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
t.Cache.Delete(cacheKey)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reqCacheControl := parseCacheControl(req.Header)
|
||||
if _, ok := reqCacheControl["only-if-cached"]; ok {
|
||||
resp = newGatewayTimeoutResponse(req)
|
||||
} else {
|
||||
resp, err = transport.RoundTrip(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cacheable && canStore(parseCacheControl(req.Header), parseCacheControl(resp.Header)) {
|
||||
for _, varyKey := range headerAllCommaSepValues(resp.Header, "vary") {
|
||||
varyKey = http.CanonicalHeaderKey(varyKey)
|
||||
fakeHeader := "X-Varied-" + varyKey
|
||||
reqValue := req.Header.Get(varyKey)
|
||||
if reqValue != "" {
|
||||
resp.Header.Set(fakeHeader, reqValue)
|
||||
}
|
||||
}
|
||||
switch req.Method {
|
||||
case "GET":
|
||||
// Delay caching until EOF is reached.
|
||||
resp.Body = &cachingReadCloser{
|
||||
R: resp.Body,
|
||||
OnEOF: func(r io.Reader) {
|
||||
resp := *resp
|
||||
resp.Body = ioutil.NopCloser(r)
|
||||
respBytes, err := httputil.DumpResponse(&resp, true)
|
||||
if err == nil {
|
||||
t.Cache.Set(cacheKey, respBytes)
|
||||
}
|
||||
},
|
||||
}
|
||||
default:
|
||||
respBytes, err := httputil.DumpResponse(resp, true)
|
||||
if err == nil {
|
||||
t.Cache.Set(cacheKey, respBytes)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t.Cache.Delete(cacheKey)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ErrNoDateHeader indicates that the HTTP headers contained no Date header.
|
||||
var ErrNoDateHeader = errors.New("no Date header")
|
||||
|
||||
// Date parses and returns the value of the Date header.
|
||||
func Date(respHeaders http.Header) (date time.Time, err error) {
|
||||
dateHeader := respHeaders.Get("date")
|
||||
if dateHeader == "" {
|
||||
err = ErrNoDateHeader
|
||||
return
|
||||
}
|
||||
|
||||
return time.Parse(time.RFC1123, dateHeader)
|
||||
}
|
||||
|
||||
type realClock struct{}
|
||||
|
||||
func (c *realClock) since(d time.Time) time.Duration {
|
||||
return time.Since(d)
|
||||
}
|
||||
|
||||
type timer interface {
|
||||
since(d time.Time) time.Duration
|
||||
}
|
||||
|
||||
var clock timer = &realClock{}
|
||||
|
||||
// getFreshness will return one of fresh/stale/transparent based on the cache-control
|
||||
// values of the request and the response
|
||||
//
|
||||
// fresh indicates the response can be returned
|
||||
// stale indicates that the response needs validating before it is returned
|
||||
// transparent indicates the response should not be used to fulfil the request
|
||||
//
|
||||
// Because this is only a private cache, 'public' and 'private' in cache-control aren't
|
||||
// signficant. Similarly, smax-age isn't used.
|
||||
func getFreshness(respHeaders, reqHeaders http.Header) (freshness int) {
|
||||
respCacheControl := parseCacheControl(respHeaders)
|
||||
reqCacheControl := parseCacheControl(reqHeaders)
|
||||
if _, ok := reqCacheControl["no-cache"]; ok {
|
||||
return transparent
|
||||
}
|
||||
if _, ok := respCacheControl["no-cache"]; ok {
|
||||
return stale
|
||||
}
|
||||
if _, ok := reqCacheControl["only-if-cached"]; ok {
|
||||
return fresh
|
||||
}
|
||||
|
||||
date, err := Date(respHeaders)
|
||||
if err != nil {
|
||||
return stale
|
||||
}
|
||||
currentAge := clock.since(date)
|
||||
|
||||
var lifetime time.Duration
|
||||
var zeroDuration time.Duration
|
||||
|
||||
// If a response includes both an Expires header and a max-age directive,
|
||||
// the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
|
||||
if maxAge, ok := respCacheControl["max-age"]; ok {
|
||||
lifetime, err = time.ParseDuration(maxAge + "s")
|
||||
if err != nil {
|
||||
lifetime = zeroDuration
|
||||
}
|
||||
} else {
|
||||
expiresHeader := respHeaders.Get("Expires")
|
||||
if expiresHeader != "" {
|
||||
expires, err := time.Parse(time.RFC1123, expiresHeader)
|
||||
if err != nil {
|
||||
lifetime = zeroDuration
|
||||
} else {
|
||||
lifetime = expires.Sub(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if maxAge, ok := reqCacheControl["max-age"]; ok {
|
||||
// the client is willing to accept a response whose age is no greater than the specified time in seconds
|
||||
lifetime, err = time.ParseDuration(maxAge + "s")
|
||||
if err != nil {
|
||||
lifetime = zeroDuration
|
||||
}
|
||||
}
|
||||
if minfresh, ok := reqCacheControl["min-fresh"]; ok {
|
||||
// the client wants a response that will still be fresh for at least the specified number of seconds.
|
||||
minfreshDuration, err := time.ParseDuration(minfresh + "s")
|
||||
if err == nil {
|
||||
currentAge = time.Duration(currentAge + minfreshDuration)
|
||||
}
|
||||
}
|
||||
|
||||
if maxstale, ok := reqCacheControl["max-stale"]; ok {
|
||||
// Indicates that the client is willing to accept a response that has exceeded its expiration time.
|
||||
// If max-stale is assigned a value, then the client is willing to accept a response that has exceeded
|
||||
// its expiration time by no more than the specified number of seconds.
|
||||
// If no value is assigned to max-stale, then the client is willing to accept a stale response of any age.
|
||||
//
|
||||
// Responses served only because of a max-stale value are supposed to have a Warning header added to them,
|
||||
// but that seems like a hassle, and is it actually useful? If so, then there needs to be a different
|
||||
// return-value available here.
|
||||
if maxstale == "" {
|
||||
return fresh
|
||||
}
|
||||
maxstaleDuration, err := time.ParseDuration(maxstale + "s")
|
||||
if err == nil {
|
||||
currentAge = time.Duration(currentAge - maxstaleDuration)
|
||||
}
|
||||
}
|
||||
|
||||
if lifetime > currentAge {
|
||||
return fresh
|
||||
}
|
||||
|
||||
return stale
|
||||
}
|
||||
|
||||
// Returns true if either the request or the response includes the stale-if-error
|
||||
// cache control extension: https://tools.ietf.org/html/rfc5861
|
||||
func canStaleOnError(respHeaders, reqHeaders http.Header) bool {
|
||||
respCacheControl := parseCacheControl(respHeaders)
|
||||
reqCacheControl := parseCacheControl(reqHeaders)
|
||||
|
||||
var err error
|
||||
lifetime := time.Duration(-1)
|
||||
|
||||
if staleMaxAge, ok := respCacheControl["stale-if-error"]; ok {
|
||||
if staleMaxAge != "" {
|
||||
lifetime, err = time.ParseDuration(staleMaxAge + "s")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if staleMaxAge, ok := reqCacheControl["stale-if-error"]; ok {
|
||||
if staleMaxAge != "" {
|
||||
lifetime, err = time.ParseDuration(staleMaxAge + "s")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if lifetime >= 0 {
|
||||
date, err := Date(respHeaders)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
currentAge := clock.since(date)
|
||||
if lifetime > currentAge {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func getEndToEndHeaders(respHeaders http.Header) []string {
|
||||
// These headers are always hop-by-hop
|
||||
hopByHopHeaders := map[string]struct{}{
|
||||
"Connection": struct{}{},
|
||||
"Keep-Alive": struct{}{},
|
||||
"Proxy-Authenticate": struct{}{},
|
||||
"Proxy-Authorization": struct{}{},
|
||||
"Te": struct{}{},
|
||||
"Trailers": struct{}{},
|
||||
"Transfer-Encoding": struct{}{},
|
||||
"Upgrade": struct{}{},
|
||||
}
|
||||
|
||||
for _, extra := range strings.Split(respHeaders.Get("connection"), ",") {
|
||||
// any header listed in connection, if present, is also considered hop-by-hop
|
||||
if strings.Trim(extra, " ") != "" {
|
||||
hopByHopHeaders[http.CanonicalHeaderKey(extra)] = struct{}{}
|
||||
}
|
||||
}
|
||||
endToEndHeaders := []string{}
|
||||
for respHeader, _ := range respHeaders {
|
||||
if _, ok := hopByHopHeaders[respHeader]; !ok {
|
||||
endToEndHeaders = append(endToEndHeaders, respHeader)
|
||||
}
|
||||
}
|
||||
return endToEndHeaders
|
||||
}
|
||||
|
||||
func canStore(reqCacheControl, respCacheControl cacheControl) (canStore bool) {
|
||||
if _, ok := respCacheControl["no-store"]; ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := reqCacheControl["no-store"]; ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func newGatewayTimeoutResponse(req *http.Request) *http.Response {
|
||||
var braw bytes.Buffer
|
||||
braw.WriteString("HTTP/1.1 504 Gateway Timeout\r\n\r\n")
|
||||
resp, err := http.ReadResponse(bufio.NewReader(&braw), req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
// (This function copyright goauth2 authors: https://code.google.com/p/goauth2)
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
// shallow copy of the struct
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
// deep copy of the Header
|
||||
r2.Header = make(http.Header)
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = s
|
||||
}
|
||||
return r2
|
||||
}
|
||||
|
||||
type cacheControl map[string]string
|
||||
|
||||
func parseCacheControl(headers http.Header) cacheControl {
|
||||
cc := cacheControl{}
|
||||
ccHeader := headers.Get("Cache-Control")
|
||||
for _, part := range strings.Split(ccHeader, ",") {
|
||||
part = strings.Trim(part, " ")
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
if strings.ContainsRune(part, '=') {
|
||||
keyval := strings.Split(part, "=")
|
||||
cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
|
||||
} else {
|
||||
cc[part] = ""
|
||||
}
|
||||
}
|
||||
return cc
|
||||
}
|
||||
|
||||
// headerAllCommaSepValues returns all comma-separated values (each
|
||||
// with whitespace trimmed) for header name in headers. According to
|
||||
// Section 4.2 of the HTTP/1.1 spec
|
||||
// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2),
|
||||
// values from multiple occurrences of a header should be concatenated, if
|
||||
// the header's value is a comma-separated list.
|
||||
func headerAllCommaSepValues(headers http.Header, name string) []string {
|
||||
var vals []string
|
||||
for _, val := range headers[http.CanonicalHeaderKey(name)] {
|
||||
fields := strings.Split(val, ",")
|
||||
for i, f := range fields {
|
||||
fields[i] = strings.TrimSpace(f)
|
||||
}
|
||||
vals = append(vals, fields...)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// cachingReadCloser is a wrapper around ReadCloser R that calls OnEOF
|
||||
// handler with a full copy of the content read from R when EOF is
|
||||
// reached.
|
||||
type cachingReadCloser struct {
|
||||
// Underlying ReadCloser.
|
||||
R io.ReadCloser
|
||||
// OnEOF is called with a copy of the content of R when EOF is reached.
|
||||
OnEOF func(io.Reader)
|
||||
|
||||
buf bytes.Buffer // buf stores a copy of the content of R.
|
||||
}
|
||||
|
||||
// Read reads the next len(p) bytes from R or until R is drained. The
|
||||
// return value n is the number of bytes read. If R has no data to
|
||||
// return, err is io.EOF and OnEOF is called with a full copy of what
|
||||
// has been read so far.
|
||||
func (r *cachingReadCloser) Read(p []byte) (n int, err error) {
|
||||
n, err = r.R.Read(p)
|
||||
r.buf.Write(p[:n])
|
||||
if err == io.EOF {
|
||||
r.OnEOF(bytes.NewReader(r.buf.Bytes()))
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *cachingReadCloser) Close() error {
|
||||
return r.R.Close()
|
||||
}
|
||||
|
||||
// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation
|
||||
func NewMemoryCacheTransport() *Transport {
|
||||
c := NewMemoryCache()
|
||||
t := NewTransport(c)
|
||||
return t
|
||||
}
|
||||
5
vendor/github.com/json-iterator/go/.gitignore
generated
vendored
5
vendor/github.com/json-iterator/go/.gitignore
generated
vendored
@@ -1,3 +1,4 @@
|
||||
.idea
|
||||
/vendor
|
||||
/bug_test.go
|
||||
/coverage.txt
|
||||
/profile.out
|
||||
/.idea
|
||||
|
||||
1
vendor/github.com/json-iterator/go/.travis.yml
generated
vendored
1
vendor/github.com/json-iterator/go/.travis.yml
generated
vendored
@@ -2,6 +2,7 @@ language: go
|
||||
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.x
|
||||
|
||||
before_install:
|
||||
- go get -t -v ./...
|
||||
|
||||
27
vendor/github.com/json-iterator/go/Gopkg.lock
generated
vendored
Normal file
27
vendor/github.com/json-iterator/go/Gopkg.lock
generated
vendored
Normal file
@@ -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
vendor/github.com/json-iterator/go/Gopkg.toml
generated
vendored
Normal file
26
vendor/github.com/json-iterator/go/Gopkg.toml
generated
vendored
Normal file
@@ -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"
|
||||
15
vendor/github.com/json-iterator/go/README.md
generated
vendored
15
vendor/github.com/json-iterator/go/README.md
generated
vendored
@@ -8,6 +8,8 @@
|
||||
|
||||
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
|
||||
```
|
||||
@@ -29,6 +31,9 @@ Raw Result (easyjson requires static code generation)
|
||||
| easyjson encode | 883 ns/op | 576 B/op | 3 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
|
||||
|
||||
100% compatibility with standard lib
|
||||
@@ -44,7 +49,9 @@ with
|
||||
|
||||
```go
|
||||
import "github.com/json-iterator/go"
|
||||
jsoniter.Marshal(&data)
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
json.Marshal(&data)
|
||||
```
|
||||
|
||||
Replace
|
||||
@@ -58,7 +65,9 @@ with
|
||||
|
||||
```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)
|
||||
@@ -76,5 +85,7 @@ Contributors
|
||||
* [thockin](https://github.com/thockin)
|
||||
* [mattn](https://github.com/mattn)
|
||||
* [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)
|
||||
|
||||
@@ -16,15 +16,6 @@ func Unmarshal(data []byte, v interface{}) error {
|
||||
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
|
||||
func UnmarshalFromString(str string, v interface{}) error {
|
||||
return ConfigDefault.UnmarshalFromString(str, v)
|
||||
@@ -71,6 +62,11 @@ type Decoder struct {
|
||||
|
||||
// Decode decode JSON into interface{}
|
||||
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)
|
||||
err := adapter.iter.Error
|
||||
if err == io.EOF {
|
||||
@@ -81,7 +77,14 @@ func (adapter *Decoder) Decode(obj interface{}) error {
|
||||
|
||||
// More is there more?
|
||||
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
|
||||
@@ -90,11 +93,21 @@ func (adapter *Decoder) Buffered() io.Reader {
|
||||
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() {
|
||||
origCfg := adapter.iter.cfg.configBeforeFrozen
|
||||
origCfg.UseNumber = true
|
||||
adapter.iter.cfg = origCfg.Froze().(*frozenConfig)
|
||||
cfg := adapter.iter.cfg.configBeforeFrozen
|
||||
cfg.UseNumber = true
|
||||
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
|
||||
@@ -110,18 +123,26 @@ type Encoder struct {
|
||||
// Encode encode interface{} as JSON to io.Writer
|
||||
func (adapter *Encoder) Encode(val interface{}) error {
|
||||
adapter.stream.WriteVal(val)
|
||||
adapter.stream.WriteRaw("\n")
|
||||
adapter.stream.Flush()
|
||||
return adapter.stream.Error
|
||||
}
|
||||
|
||||
// SetIndent set the indention. Prefix is not supported
|
||||
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
|
||||
func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
|
||||
config := adapter.stream.cfg.configBeforeFrozen
|
||||
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)
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/modern-go/reflect2"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Any generic object representation.
|
||||
@@ -24,7 +28,6 @@ type Any interface {
|
||||
ToString() string
|
||||
ToVal(val interface{})
|
||||
Get(path ...interface{}) Any
|
||||
// TODO: add Set
|
||||
Size() int
|
||||
Keys() []string
|
||||
GetInterface() interface{}
|
||||
@@ -34,7 +37,7 @@ type Any interface {
|
||||
type baseAny struct{}
|
||||
|
||||
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 {
|
||||
@@ -88,7 +91,7 @@ func Wrap(val interface{}) Any {
|
||||
if isAny {
|
||||
return asAny
|
||||
}
|
||||
typ := reflect.TypeOf(val)
|
||||
typ := reflect2.TypeOf(val)
|
||||
switch typ.Kind() {
|
||||
case reflect.Slice:
|
||||
return wrapArray(val)
|
||||
@@ -99,6 +102,9 @@ func Wrap(val interface{}) Any {
|
||||
case reflect.String:
|
||||
return WrapString(val.(string))
|
||||
case reflect.Int:
|
||||
if strconv.IntSize == 32 {
|
||||
return WrapInt32(int32(val.(int)))
|
||||
}
|
||||
return WrapInt64(int64(val.(int)))
|
||||
case reflect.Int8:
|
||||
return WrapInt32(int32(val.(int8)))
|
||||
@@ -109,7 +115,15 @@ func Wrap(val interface{}) Any {
|
||||
case reflect.Int64:
|
||||
return WrapInt64(val.(int64))
|
||||
case reflect.Uint:
|
||||
if strconv.IntSize == 32 {
|
||||
return WrapUint32(uint32(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:
|
||||
return WrapUint32(uint32(val.(uint8)))
|
||||
case reflect.Uint16:
|
||||
@@ -157,6 +171,8 @@ func (iter *Iterator) readAny() Any {
|
||||
return iter.readArrayAny()
|
||||
case '-':
|
||||
return iter.readNumberAny(false)
|
||||
case 0:
|
||||
return &invalidAny{baseAny{}, errors.New("input is empty")}
|
||||
default:
|
||||
return iter.readNumberAny(true)
|
||||
}
|
||||
@@ -240,3 +256,66 @@ func locatePath(iter *Iterator, path []interface{}) Any {
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package jsoniter
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type numberLazyAny struct {
|
||||
baseAny
|
||||
@@ -29,7 +32,9 @@ func (any *numberLazyAny) ToInt() int {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadInt()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -37,7 +42,9 @@ func (any *numberLazyAny) ToInt32() int32 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadInt32()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -45,7 +52,9 @@ func (any *numberLazyAny) ToInt64() int64 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadInt64()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -53,7 +62,9 @@ func (any *numberLazyAny) ToUint() uint {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadUint()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -61,7 +72,9 @@ func (any *numberLazyAny) ToUint32() uint32 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadUint32()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -69,7 +82,9 @@ func (any *numberLazyAny) ToUint64() uint64 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadUint64()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -77,7 +92,9 @@ func (any *numberLazyAny) ToFloat32() float32 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadFloat32()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -85,7 +102,9 @@ func (any *numberLazyAny) ToFloat64() float64 {
|
||||
iter := any.cfg.BorrowIterator(any.buf)
|
||||
defer any.cfg.ReturnIterator(iter)
|
||||
val := iter.ReadFloat64()
|
||||
any.err = iter.Error
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
any.err = iter.Error
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ func (any *stringAny) Get(path ...interface{}) Any {
|
||||
if len(path) == 0 {
|
||||
return 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 *stringAny) Parse() *Iterator {
|
||||
12
vendor/github.com/json-iterator/go/build.sh
generated
vendored
Executable file
12
vendor/github.com/json-iterator/go/build.sh
generated
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then
|
||||
mkdir -p /tmp/build-golang/src/github.com/json-iterator
|
||||
ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go
|
||||
fi
|
||||
export GOPATH=/tmp/build-golang
|
||||
go get -u github.com/golang/dep/cmd/dep
|
||||
cd /tmp/build-golang/src/github.com/json-iterator/go
|
||||
exec $GOPATH/bin/dep ensure -update
|
||||
372
vendor/github.com/json-iterator/go/config.go
generated
vendored
Normal file
372
vendor/github.com/json-iterator/go/config.go
generated
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/modern-go/concurrent"
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
// Config customize how the API should behave.
|
||||
// The API is created from Config by Froze.
|
||||
type Config struct {
|
||||
IndentionStep int
|
||||
MarshalFloatWith6Digits bool
|
||||
EscapeHTML bool
|
||||
SortMapKeys bool
|
||||
UseNumber bool
|
||||
DisallowUnknownFields bool
|
||||
TagKey string
|
||||
OnlyTaggedField bool
|
||||
ValidateJsonRawMessage bool
|
||||
ObjectFieldMustBeSimpleString bool
|
||||
CaseSensitive bool
|
||||
}
|
||||
|
||||
// API the public interface of this package.
|
||||
// Primary Marshal and Unmarshal.
|
||||
type API interface {
|
||||
IteratorPool
|
||||
StreamPool
|
||||
MarshalToString(v interface{}) (string, error)
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
|
||||
UnmarshalFromString(str string, v interface{}) error
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Get(data []byte, path ...interface{}) Any
|
||||
NewEncoder(writer io.Writer) *Encoder
|
||||
NewDecoder(reader io.Reader) *Decoder
|
||||
Valid(data []byte) bool
|
||||
RegisterExtension(extension Extension)
|
||||
DecoderOf(typ reflect2.Type) ValDecoder
|
||||
EncoderOf(typ reflect2.Type) ValEncoder
|
||||
}
|
||||
|
||||
// ConfigDefault the default API
|
||||
var ConfigDefault = Config{
|
||||
EscapeHTML: true,
|
||||
}.Froze()
|
||||
|
||||
// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
|
||||
var ConfigCompatibleWithStandardLibrary = Config{
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
ValidateJsonRawMessage: true,
|
||||
}.Froze()
|
||||
|
||||
// ConfigFastest marshals float with only 6 digits precision
|
||||
var ConfigFastest = Config{
|
||||
EscapeHTML: false,
|
||||
MarshalFloatWith6Digits: true, // will lose precession
|
||||
ObjectFieldMustBeSimpleString: true, // do not unescape object field
|
||||
}.Froze()
|
||||
|
||||
type frozenConfig struct {
|
||||
configBeforeFrozen Config
|
||||
sortMapKeys bool
|
||||
indentionStep int
|
||||
objectFieldMustBeSimpleString bool
|
||||
onlyTaggedField bool
|
||||
disallowUnknownFields bool
|
||||
decoderCache *concurrent.Map
|
||||
encoderCache *concurrent.Map
|
||||
extensions []Extension
|
||||
streamPool *sync.Pool
|
||||
iteratorPool *sync.Pool
|
||||
caseSensitive bool
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) initCache() {
|
||||
cfg.decoderCache = concurrent.NewMap()
|
||||
cfg.encoderCache = concurrent.NewMap()
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
|
||||
cfg.decoderCache.Store(cacheKey, decoder)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
|
||||
cfg.encoderCache.Store(cacheKey, encoder)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
|
||||
decoder, found := cfg.decoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return decoder.(ValDecoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
|
||||
encoder, found := cfg.encoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return encoder.(ValEncoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var cfgCache = concurrent.NewMap()
|
||||
|
||||
func getFrozenConfigFromCache(cfg Config) *frozenConfig {
|
||||
obj, found := cfgCache.Load(cfg)
|
||||
if found {
|
||||
return obj.(*frozenConfig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
|
||||
cfgCache.Store(cfg, frozenConfig)
|
||||
}
|
||||
|
||||
// Froze forge API from config
|
||||
func (cfg Config) Froze() API {
|
||||
api := &frozenConfig{
|
||||
sortMapKeys: cfg.SortMapKeys,
|
||||
indentionStep: cfg.IndentionStep,
|
||||
objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
|
||||
onlyTaggedField: cfg.OnlyTaggedField,
|
||||
disallowUnknownFields: cfg.DisallowUnknownFields,
|
||||
caseSensitive: cfg.CaseSensitive,
|
||||
}
|
||||
api.streamPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return NewStream(api, nil, 512)
|
||||
},
|
||||
}
|
||||
api.iteratorPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return NewIterator(api)
|
||||
},
|
||||
}
|
||||
api.initCache()
|
||||
encoderExtension := EncoderExtension{}
|
||||
decoderExtension := DecoderExtension{}
|
||||
if cfg.MarshalFloatWith6Digits {
|
||||
api.marshalFloatWith6Digits(encoderExtension)
|
||||
}
|
||||
if cfg.EscapeHTML {
|
||||
api.escapeHTML(encoderExtension)
|
||||
}
|
||||
if cfg.UseNumber {
|
||||
api.useNumber(decoderExtension)
|
||||
}
|
||||
if cfg.ValidateJsonRawMessage {
|
||||
api.validateJsonRawMessage(encoderExtension)
|
||||
}
|
||||
if len(encoderExtension) > 0 {
|
||||
api.extensions = append(api.extensions, encoderExtension)
|
||||
}
|
||||
if len(decoderExtension) > 0 {
|
||||
api.extensions = append(api.extensions, decoderExtension)
|
||||
}
|
||||
api.configBeforeFrozen = cfg
|
||||
return api
|
||||
}
|
||||
|
||||
func (cfg Config) frozeWithCacheReuse() *frozenConfig {
|
||||
api := getFrozenConfigFromCache(cfg)
|
||||
if api != nil {
|
||||
return api
|
||||
}
|
||||
api = cfg.Froze().(*frozenConfig)
|
||||
addFrozenConfigToCache(cfg, api)
|
||||
return api
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
|
||||
encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
|
||||
rawMessage := *(*json.RawMessage)(ptr)
|
||||
iter := cfg.BorrowIterator([]byte(rawMessage))
|
||||
iter.Read()
|
||||
if iter.Error != nil {
|
||||
stream.WriteRaw("null")
|
||||
} else {
|
||||
cfg.ReturnIterator(iter)
|
||||
stream.WriteRaw(string(rawMessage))
|
||||
}
|
||||
}, func(ptr unsafe.Pointer) bool {
|
||||
return false
|
||||
}}
|
||||
extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
|
||||
extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
|
||||
extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
|
||||
exitingValue := *((*interface{})(ptr))
|
||||
if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr {
|
||||
iter.ReadVal(exitingValue)
|
||||
return
|
||||
}
|
||||
if iter.WhatIsNext() == NumberValue {
|
||||
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
|
||||
} else {
|
||||
*((*interface{})(ptr)) = iter.Read()
|
||||
}
|
||||
}}
|
||||
}
|
||||
func (cfg *frozenConfig) getTagKey() string {
|
||||
tagKey := cfg.configBeforeFrozen.TagKey
|
||||
if tagKey == "" {
|
||||
return "json"
|
||||
}
|
||||
return tagKey
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) RegisterExtension(extension Extension) {
|
||||
cfg.extensions = append(cfg.extensions, extension)
|
||||
}
|
||||
|
||||
type lossyFloat32Encoder struct {
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat32Lossy(*((*float32)(ptr)))
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float32)(ptr)) == 0
|
||||
}
|
||||
|
||||
type lossyFloat64Encoder struct {
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat64Lossy(*((*float64)(ptr)))
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float64)(ptr)) == 0
|
||||
}
|
||||
|
||||
// EnableLossyFloatMarshalling keeps 10**(-6) precision
|
||||
// for float variables for better performance.
|
||||
func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
|
||||
// for better performance
|
||||
extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
|
||||
extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
|
||||
}
|
||||
|
||||
type htmlEscapedStringEncoder struct {
|
||||
}
|
||||
|
||||
func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
str := *((*string)(ptr))
|
||||
stream.WriteStringWithHTMLEscaped(str)
|
||||
}
|
||||
|
||||
func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*string)(ptr)) == ""
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
|
||||
encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) cleanDecoders() {
|
||||
typeDecoders = map[string]ValDecoder{}
|
||||
fieldDecoders = map[string]ValDecoder{}
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) cleanEncoders() {
|
||||
typeEncoders = map[string]ValEncoder{}
|
||||
fieldEncoders = map[string]ValEncoder{}
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
|
||||
stream := cfg.BorrowStream(nil)
|
||||
defer cfg.ReturnStream(stream)
|
||||
stream.WriteVal(v)
|
||||
if stream.Error != nil {
|
||||
return "", stream.Error
|
||||
}
|
||||
return string(stream.Buffer()), nil
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
|
||||
stream := cfg.BorrowStream(nil)
|
||||
defer cfg.ReturnStream(stream)
|
||||
stream.WriteVal(v)
|
||||
if stream.Error != nil {
|
||||
return nil, stream.Error
|
||||
}
|
||||
result := stream.Buffer()
|
||||
copied := make([]byte, len(result))
|
||||
copy(copied, result)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||
if prefix != "" {
|
||||
panic("prefix is not supported")
|
||||
}
|
||||
for _, r := range indent {
|
||||
if r != ' ' {
|
||||
panic("indent can only be space")
|
||||
}
|
||||
}
|
||||
newCfg := cfg.configBeforeFrozen
|
||||
newCfg.IndentionStep = len(indent)
|
||||
return newCfg.frozeWithCacheReuse().Marshal(v)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
|
||||
data := []byte(str)
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
iter.ReadVal(v)
|
||||
c := iter.nextToken()
|
||||
if c == 0 {
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
return locatePath(iter, path)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
iter.ReadVal(v)
|
||||
c := iter.nextToken()
|
||||
if c == 0 {
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder {
|
||||
stream := NewStream(cfg, writer, 512)
|
||||
return &Encoder{stream}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder {
|
||||
iter := Parse(cfg, reader, 512)
|
||||
return &Decoder{iter}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Valid(data []byte) bool {
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
iter.Skip()
|
||||
return iter.Error == nil
|
||||
}
|
||||
312
vendor/github.com/json-iterator/go/feature_config.go
generated
vendored
312
vendor/github.com/json-iterator/go/feature_config.go
generated
vendored
@@ -1,312 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Config customize how the API should behave.
|
||||
// The API is created from Config by Froze.
|
||||
type Config struct {
|
||||
IndentionStep int
|
||||
MarshalFloatWith6Digits bool
|
||||
EscapeHTML bool
|
||||
SortMapKeys bool
|
||||
UseNumber bool
|
||||
TagKey string
|
||||
}
|
||||
|
||||
type frozenConfig struct {
|
||||
configBeforeFrozen Config
|
||||
sortMapKeys bool
|
||||
indentionStep int
|
||||
decoderCache unsafe.Pointer
|
||||
encoderCache unsafe.Pointer
|
||||
extensions []Extension
|
||||
streamPool chan *Stream
|
||||
iteratorPool chan *Iterator
|
||||
}
|
||||
|
||||
// API the public interface of this package.
|
||||
// Primary Marshal and Unmarshal.
|
||||
type API interface {
|
||||
IteratorPool
|
||||
StreamPool
|
||||
MarshalToString(v interface{}) (string, error)
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
|
||||
UnmarshalFromString(str string, v interface{}) error
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Get(data []byte, path ...interface{}) Any
|
||||
NewEncoder(writer io.Writer) *Encoder
|
||||
NewDecoder(reader io.Reader) *Decoder
|
||||
}
|
||||
|
||||
// ConfigDefault the default API
|
||||
var ConfigDefault = Config{
|
||||
EscapeHTML: true,
|
||||
}.Froze()
|
||||
|
||||
// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
|
||||
var ConfigCompatibleWithStandardLibrary = Config{
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
}.Froze()
|
||||
|
||||
// ConfigFastest marshals float with only 6 digits precision
|
||||
var ConfigFastest = Config{
|
||||
EscapeHTML: false,
|
||||
MarshalFloatWith6Digits: true,
|
||||
}.Froze()
|
||||
|
||||
// Froze forge API from config
|
||||
func (cfg Config) Froze() API {
|
||||
// TODO: cache frozen config
|
||||
frozenConfig := &frozenConfig{
|
||||
sortMapKeys: cfg.SortMapKeys,
|
||||
indentionStep: cfg.IndentionStep,
|
||||
streamPool: make(chan *Stream, 16),
|
||||
iteratorPool: make(chan *Iterator, 16),
|
||||
}
|
||||
atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]ValDecoder{}))
|
||||
atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]ValEncoder{}))
|
||||
if cfg.MarshalFloatWith6Digits {
|
||||
frozenConfig.marshalFloatWith6Digits()
|
||||
}
|
||||
if cfg.EscapeHTML {
|
||||
frozenConfig.escapeHTML()
|
||||
}
|
||||
if cfg.UseNumber {
|
||||
frozenConfig.useNumber()
|
||||
}
|
||||
frozenConfig.configBeforeFrozen = cfg
|
||||
return frozenConfig
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) useNumber() {
|
||||
cfg.addDecoderToCache(reflect.TypeOf((*interface{})(nil)).Elem(), &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.WhatIsNext() == NumberValue {
|
||||
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
|
||||
} else {
|
||||
*((*interface{})(ptr)) = iter.Read()
|
||||
}
|
||||
}})
|
||||
}
|
||||
func (cfg *frozenConfig) getTagKey() string {
|
||||
tagKey := cfg.configBeforeFrozen.TagKey
|
||||
if tagKey == "" {
|
||||
return "json"
|
||||
}
|
||||
return tagKey
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) registerExtension(extension Extension) {
|
||||
cfg.extensions = append(cfg.extensions, extension)
|
||||
}
|
||||
|
||||
type lossyFloat32Encoder struct {
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat32Lossy(*((*float32)(ptr)))
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat32Encoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float32)(ptr)) == 0
|
||||
}
|
||||
|
||||
type lossyFloat64Encoder struct {
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat64Lossy(*((*float64)(ptr)))
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat64Encoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float64)(ptr)) == 0
|
||||
}
|
||||
|
||||
// EnableLossyFloatMarshalling keeps 10**(-6) precision
|
||||
// for float variables for better performance.
|
||||
func (cfg *frozenConfig) marshalFloatWith6Digits() {
|
||||
// for better performance
|
||||
cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &lossyFloat32Encoder{})
|
||||
cfg.addEncoderToCache(reflect.TypeOf((*float64)(nil)).Elem(), &lossyFloat64Encoder{})
|
||||
}
|
||||
|
||||
type htmlEscapedStringEncoder struct {
|
||||
}
|
||||
|
||||
func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
str := *((*string)(ptr))
|
||||
stream.WriteStringWithHTMLEscaped(str)
|
||||
}
|
||||
|
||||
func (encoder *htmlEscapedStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*string)(ptr)) == ""
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) escapeHTML() {
|
||||
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
|
||||
done := false
|
||||
for !done {
|
||||
ptr := atomic.LoadPointer(&cfg.decoderCache)
|
||||
cache := *(*map[reflect.Type]ValDecoder)(ptr)
|
||||
copied := map[reflect.Type]ValDecoder{}
|
||||
for k, v := range cache {
|
||||
copied[k] = v
|
||||
}
|
||||
copied[cacheKey] = decoder
|
||||
done = atomic.CompareAndSwapPointer(&cfg.decoderCache, ptr, unsafe.Pointer(&copied))
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
|
||||
done := false
|
||||
for !done {
|
||||
ptr := atomic.LoadPointer(&cfg.encoderCache)
|
||||
cache := *(*map[reflect.Type]ValEncoder)(ptr)
|
||||
copied := map[reflect.Type]ValEncoder{}
|
||||
for k, v := range cache {
|
||||
copied[k] = v
|
||||
}
|
||||
copied[cacheKey] = encoder
|
||||
done = atomic.CompareAndSwapPointer(&cfg.encoderCache, ptr, unsafe.Pointer(&copied))
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
|
||||
ptr := atomic.LoadPointer(&cfg.decoderCache)
|
||||
cache := *(*map[reflect.Type]ValDecoder)(ptr)
|
||||
return cache[cacheKey]
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
|
||||
ptr := atomic.LoadPointer(&cfg.encoderCache)
|
||||
cache := *(*map[reflect.Type]ValEncoder)(ptr)
|
||||
return cache[cacheKey]
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) cleanDecoders() {
|
||||
typeDecoders = map[string]ValDecoder{}
|
||||
fieldDecoders = map[string]ValDecoder{}
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) cleanEncoders() {
|
||||
typeEncoders = map[string]ValEncoder{}
|
||||
fieldEncoders = map[string]ValEncoder{}
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
|
||||
stream := cfg.BorrowStream(nil)
|
||||
defer cfg.ReturnStream(stream)
|
||||
stream.WriteVal(v)
|
||||
if stream.Error != nil {
|
||||
return "", stream.Error
|
||||
}
|
||||
return string(stream.Buffer()), nil
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
|
||||
stream := cfg.BorrowStream(nil)
|
||||
defer cfg.ReturnStream(stream)
|
||||
stream.WriteVal(v)
|
||||
if stream.Error != nil {
|
||||
return nil, stream.Error
|
||||
}
|
||||
result := stream.Buffer()
|
||||
copied := make([]byte, len(result))
|
||||
copy(copied, result)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||
if prefix != "" {
|
||||
panic("prefix is not supported")
|
||||
}
|
||||
for _, r := range indent {
|
||||
if r != ' ' {
|
||||
panic("indent can only be space")
|
||||
}
|
||||
}
|
||||
newCfg := cfg.configBeforeFrozen
|
||||
newCfg.IndentionStep = len(indent)
|
||||
return newCfg.Froze().Marshal(v)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
|
||||
data := []byte(str)
|
||||
data = data[:lastNotSpacePos(data)]
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
iter.ReadVal(v)
|
||||
if iter.head == iter.tail {
|
||||
iter.loadMore()
|
||||
}
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.ReportError("UnmarshalFromString", "there are bytes left after unmarshal")
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
return locatePath(iter, path)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
|
||||
data = data[:lastNotSpacePos(data)]
|
||||
iter := cfg.BorrowIterator(data)
|
||||
defer cfg.ReturnIterator(iter)
|
||||
typ := reflect.TypeOf(v)
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
// return non-pointer error
|
||||
return errors.New("the second param must be ptr type")
|
||||
}
|
||||
iter.ReadVal(v)
|
||||
if iter.head == iter.tail {
|
||||
iter.loadMore()
|
||||
}
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder {
|
||||
stream := NewStream(cfg, writer, 512)
|
||||
return &Encoder{stream}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder {
|
||||
iter := Parse(cfg, reader, 512)
|
||||
return &Decoder{iter}
|
||||
}
|
||||
15
vendor/github.com/json-iterator/go/feature_json_number.go
generated
vendored
15
vendor/github.com/json-iterator/go/feature_json_number.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Number string
|
||||
|
||||
func CastJsonNumber(val interface{}) (string, bool) {
|
||||
switch typedVal := val.(type) {
|
||||
case json.Number:
|
||||
return string(typedVal), true
|
||||
case Number:
|
||||
return string(typedVal), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
691
vendor/github.com/json-iterator/go/feature_reflect.go
generated
vendored
691
vendor/github.com/json-iterator/go/feature_reflect.go
generated
vendored
@@ -1,691 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ValDecoder is an internal type registered to cache as needed.
|
||||
// Don't confuse jsoniter.ValDecoder with json.Decoder.
|
||||
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
|
||||
//
|
||||
// Reflection on type to create decoders, which is then cached
|
||||
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
|
||||
// 1. create instance of new value, for example *int will need a int to be allocated
|
||||
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
|
||||
// 3. assignment to map, both key and value will be reflect.Value
|
||||
// For a simple struct binding, it will be reflect.Value free and allocation free
|
||||
type ValDecoder interface {
|
||||
Decode(ptr unsafe.Pointer, iter *Iterator)
|
||||
}
|
||||
|
||||
// ValEncoder is an internal type registered to cache as needed.
|
||||
// Don't confuse jsoniter.ValEncoder with json.Encoder.
|
||||
// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link).
|
||||
type ValEncoder interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
Encode(ptr unsafe.Pointer, stream *Stream)
|
||||
EncodeInterface(val interface{}, stream *Stream)
|
||||
}
|
||||
|
||||
type checkIsEmpty interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
}
|
||||
|
||||
// WriteToStream the default implementation for TypeEncoder method EncodeInterface
|
||||
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
|
||||
e := (*emptyInterface)(unsafe.Pointer(&val))
|
||||
if e.word == nil {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
if reflect.TypeOf(val).Kind() == reflect.Ptr {
|
||||
encoder.Encode(unsafe.Pointer(&e.word), stream)
|
||||
} else {
|
||||
encoder.Encode(e.word, stream)
|
||||
}
|
||||
}
|
||||
|
||||
var jsonNumberType reflect.Type
|
||||
var jsoniterNumberType reflect.Type
|
||||
var jsonRawMessageType reflect.Type
|
||||
var jsoniterRawMessageType reflect.Type
|
||||
var anyType reflect.Type
|
||||
var marshalerType reflect.Type
|
||||
var unmarshalerType reflect.Type
|
||||
var textMarshalerType reflect.Type
|
||||
var textUnmarshalerType reflect.Type
|
||||
|
||||
func init() {
|
||||
jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
|
||||
jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
|
||||
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
|
||||
jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
|
||||
anyType = reflect.TypeOf((*Any)(nil)).Elem()
|
||||
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
}
|
||||
|
||||
type optionalDecoder struct {
|
||||
valueType reflect.Type
|
||||
valueDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *optionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.ReadNil() {
|
||||
*((*unsafe.Pointer)(ptr)) = nil
|
||||
} else {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
//pointer to null, we have to allocate memory to hold the value
|
||||
value := reflect.New(decoder.valueType)
|
||||
newPtr := extractInterface(value.Interface()).word
|
||||
decoder.valueDecoder.Decode(newPtr, iter)
|
||||
*((*uintptr)(ptr)) = uintptr(newPtr)
|
||||
} else {
|
||||
//reuse existing instance
|
||||
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type deferenceDecoder struct {
|
||||
// only to deference a pointer
|
||||
valueType reflect.Type
|
||||
valueDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
//pointer to null, we have to allocate memory to hold the value
|
||||
value := reflect.New(decoder.valueType)
|
||||
newPtr := extractInterface(value.Interface()).word
|
||||
decoder.valueDecoder.Decode(newPtr, iter)
|
||||
*((*uintptr)(ptr)) = uintptr(newPtr)
|
||||
} else {
|
||||
//reuse existing instance
|
||||
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
|
||||
}
|
||||
}
|
||||
|
||||
type optionalEncoder struct {
|
||||
valueEncoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *optionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
stream.WriteNil()
|
||||
} else {
|
||||
encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *optionalEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type placeholderEncoder struct {
|
||||
cfg *frozenConfig
|
||||
cacheKey reflect.Type
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
encoder.getRealEncoder().Encode(ptr, stream)
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.getRealEncoder().IsEmpty(ptr)
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) getRealEncoder() ValEncoder {
|
||||
for i := 0; i < 30; i++ {
|
||||
realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
|
||||
_, isPlaceholder := realDecoder.(*placeholderEncoder)
|
||||
if isPlaceholder {
|
||||
time.Sleep(time.Second)
|
||||
} else {
|
||||
return realDecoder
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
|
||||
}
|
||||
|
||||
type placeholderDecoder struct {
|
||||
cfg *frozenConfig
|
||||
cacheKey reflect.Type
|
||||
}
|
||||
|
||||
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
for i := 0; i < 30; i++ {
|
||||
realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
|
||||
_, isPlaceholder := realDecoder.(*placeholderDecoder)
|
||||
if isPlaceholder {
|
||||
time.Sleep(time.Second)
|
||||
} else {
|
||||
realDecoder.Decode(ptr, iter)
|
||||
return
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
|
||||
}
|
||||
|
||||
// emptyInterface is the header for an interface{} value.
|
||||
type emptyInterface struct {
|
||||
typ unsafe.Pointer
|
||||
word unsafe.Pointer
|
||||
}
|
||||
|
||||
// emptyInterface is the header for an interface with method (not interface{})
|
||||
type nonEmptyInterface struct {
|
||||
// see ../runtime/iface.go:/Itab
|
||||
itab *struct {
|
||||
ityp unsafe.Pointer // static interface type
|
||||
typ unsafe.Pointer // dynamic concrete type
|
||||
link unsafe.Pointer
|
||||
bad int32
|
||||
unused int32
|
||||
fun [100000]unsafe.Pointer // method table
|
||||
}
|
||||
word unsafe.Pointer
|
||||
}
|
||||
|
||||
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
|
||||
func (iter *Iterator) ReadVal(obj interface{}) {
|
||||
typ := reflect.TypeOf(obj)
|
||||
cacheKey := typ.Elem()
|
||||
decoder, err := decoderOfType(iter.cfg, cacheKey)
|
||||
if err != nil {
|
||||
iter.Error = err
|
||||
return
|
||||
}
|
||||
e := (*emptyInterface)(unsafe.Pointer(&obj))
|
||||
decoder.Decode(e.word, iter)
|
||||
}
|
||||
|
||||
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
|
||||
func (stream *Stream) WriteVal(val interface{}) {
|
||||
if nil == val {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
typ := reflect.TypeOf(val)
|
||||
cacheKey := typ
|
||||
encoder, err := encoderOfType(stream.cfg, cacheKey)
|
||||
if err != nil {
|
||||
stream.Error = err
|
||||
return
|
||||
}
|
||||
encoder.EncodeInterface(val, stream)
|
||||
}
|
||||
|
||||
type prefix string
|
||||
|
||||
func (p prefix) addToDecoder(decoder ValDecoder, err error) (ValDecoder, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", p, err.Error())
|
||||
}
|
||||
return decoder, err
|
||||
}
|
||||
|
||||
func (p prefix) addToEncoder(encoder ValEncoder, err error) (ValEncoder, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", p, err.Error())
|
||||
}
|
||||
return encoder, err
|
||||
}
|
||||
|
||||
func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
cacheKey := typ
|
||||
decoder := cfg.getDecoderFromCache(cacheKey)
|
||||
if decoder != nil {
|
||||
return decoder, nil
|
||||
}
|
||||
decoder = getTypeDecoderFromExtension(typ)
|
||||
if decoder != nil {
|
||||
cfg.addDecoderToCache(cacheKey, decoder)
|
||||
return decoder, nil
|
||||
}
|
||||
decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
|
||||
cfg.addDecoderToCache(cacheKey, decoder)
|
||||
decoder, err := createDecoderOfType(cfg, typ)
|
||||
for _, extension := range extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
cfg.addDecoderToCache(cacheKey, decoder)
|
||||
return decoder, err
|
||||
}
|
||||
|
||||
func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
typeName := typ.String()
|
||||
if typ == jsonRawMessageType {
|
||||
return &jsonRawMessageCodec{}, nil
|
||||
}
|
||||
if typ == jsoniterRawMessageType {
|
||||
return &jsoniterRawMessageCodec{}, nil
|
||||
}
|
||||
if typ.AssignableTo(jsonNumberType) {
|
||||
return &jsonNumberCodec{}, nil
|
||||
}
|
||||
if typ.AssignableTo(jsoniterNumberType) {
|
||||
return &jsoniterNumberCodec{}, nil
|
||||
}
|
||||
if typ.Implements(unmarshalerType) {
|
||||
templateInterface := reflect.New(typ).Elem().Interface()
|
||||
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
decoder = &optionalDecoder{typ.Elem(), decoder}
|
||||
}
|
||||
return decoder, nil
|
||||
}
|
||||
if reflect.PtrTo(typ).Implements(unmarshalerType) {
|
||||
templateInterface := reflect.New(typ).Interface()
|
||||
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
||||
return decoder, nil
|
||||
}
|
||||
if typ.Implements(textUnmarshalerType) {
|
||||
templateInterface := reflect.New(typ).Elem().Interface()
|
||||
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
decoder = &optionalDecoder{typ.Elem(), decoder}
|
||||
}
|
||||
return decoder, nil
|
||||
}
|
||||
if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
|
||||
templateInterface := reflect.New(typ).Interface()
|
||||
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
|
||||
return decoder, nil
|
||||
}
|
||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||
sliceDecoder, err := prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &base64Codec{sliceDecoder: sliceDecoder}, nil
|
||||
}
|
||||
if typ.Implements(anyType) {
|
||||
return &anyCodec{}, nil
|
||||
}
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
if typeName != "string" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
|
||||
}
|
||||
return &stringCodec{}, nil
|
||||
case reflect.Int:
|
||||
if typeName != "int" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
|
||||
}
|
||||
return &intCodec{}, nil
|
||||
case reflect.Int8:
|
||||
if typeName != "int8" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
}
|
||||
return &int8Codec{}, nil
|
||||
case reflect.Int16:
|
||||
if typeName != "int16" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
}
|
||||
return &int16Codec{}, nil
|
||||
case reflect.Int32:
|
||||
if typeName != "int32" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
}
|
||||
return &int32Codec{}, nil
|
||||
case reflect.Int64:
|
||||
if typeName != "int64" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
}
|
||||
return &int64Codec{}, nil
|
||||
case reflect.Uint:
|
||||
if typeName != "uint" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
}
|
||||
return &uintCodec{}, nil
|
||||
case reflect.Uint8:
|
||||
if typeName != "uint8" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
}
|
||||
return &uint8Codec{}, nil
|
||||
case reflect.Uint16:
|
||||
if typeName != "uint16" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
}
|
||||
return &uint16Codec{}, nil
|
||||
case reflect.Uint32:
|
||||
if typeName != "uint32" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
}
|
||||
return &uint32Codec{}, nil
|
||||
case reflect.Uintptr:
|
||||
if typeName != "uintptr" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
}
|
||||
return &uintptrCodec{}, nil
|
||||
case reflect.Uint64:
|
||||
if typeName != "uint64" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
}
|
||||
return &uint64Codec{}, nil
|
||||
case reflect.Float32:
|
||||
if typeName != "float32" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
}
|
||||
return &float32Codec{}, nil
|
||||
case reflect.Float64:
|
||||
if typeName != "float64" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
}
|
||||
return &float64Codec{}, nil
|
||||
case reflect.Bool:
|
||||
if typeName != "bool" {
|
||||
return decoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
}
|
||||
return &boolCodec{}, nil
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
|
||||
case reflect.Array:
|
||||
return prefix("[array]").addToDecoder(decoderOfArray(cfg, typ))
|
||||
case reflect.Slice:
|
||||
return prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
|
||||
case reflect.Map:
|
||||
return prefix("[map]").addToDecoder(decoderOfMap(cfg, typ))
|
||||
case reflect.Ptr:
|
||||
return prefix("[optional]").addToDecoder(decoderOfOptional(cfg, typ))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type: %v", typ)
|
||||
}
|
||||
}
|
||||
|
||||
func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
cacheKey := typ
|
||||
encoder := cfg.getEncoderFromCache(cacheKey)
|
||||
if encoder != nil {
|
||||
return encoder, nil
|
||||
}
|
||||
encoder = getTypeEncoderFromExtension(typ)
|
||||
if encoder != nil {
|
||||
cfg.addEncoderToCache(cacheKey, encoder)
|
||||
return encoder, nil
|
||||
}
|
||||
encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
|
||||
cfg.addEncoderToCache(cacheKey, encoder)
|
||||
encoder, err := createEncoderOfType(cfg, typ)
|
||||
for _, extension := range extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
cfg.addEncoderToCache(cacheKey, encoder)
|
||||
return encoder, err
|
||||
}
|
||||
|
||||
func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
if typ == jsonRawMessageType {
|
||||
return &jsonRawMessageCodec{}, nil
|
||||
}
|
||||
if typ == jsoniterRawMessageType {
|
||||
return &jsoniterRawMessageCodec{}, nil
|
||||
}
|
||||
if typ.AssignableTo(jsonNumberType) {
|
||||
return &jsonNumberCodec{}, nil
|
||||
}
|
||||
if typ.AssignableTo(jsoniterNumberType) {
|
||||
return &jsoniterNumberCodec{}, nil
|
||||
}
|
||||
if typ.Implements(marshalerType) {
|
||||
checkIsEmpty, err := createCheckIsEmpty(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templateInterface := reflect.New(typ).Elem().Interface()
|
||||
var encoder ValEncoder = &marshalerEncoder{
|
||||
templateInterface: extractInterface(templateInterface),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
}
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
encoder = &optionalEncoder{encoder}
|
||||
}
|
||||
return encoder, nil
|
||||
}
|
||||
if typ.Implements(textMarshalerType) {
|
||||
checkIsEmpty, err := createCheckIsEmpty(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templateInterface := reflect.New(typ).Elem().Interface()
|
||||
var encoder ValEncoder = &textMarshalerEncoder{
|
||||
templateInterface: extractInterface(templateInterface),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
}
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
encoder = &optionalEncoder{encoder}
|
||||
}
|
||||
return encoder, nil
|
||||
}
|
||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||
return &base64Codec{}, nil
|
||||
}
|
||||
if typ.Implements(anyType) {
|
||||
return &anyCodec{}, nil
|
||||
}
|
||||
return createEncoderOfSimpleType(cfg, typ)
|
||||
}
|
||||
|
||||
func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) {
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
return &stringCodec{}, nil
|
||||
case reflect.Int:
|
||||
return &intCodec{}, nil
|
||||
case reflect.Int8:
|
||||
return &int8Codec{}, nil
|
||||
case reflect.Int16:
|
||||
return &int16Codec{}, nil
|
||||
case reflect.Int32:
|
||||
return &int32Codec{}, nil
|
||||
case reflect.Int64:
|
||||
return &int64Codec{}, nil
|
||||
case reflect.Uint:
|
||||
return &uintCodec{}, nil
|
||||
case reflect.Uint8:
|
||||
return &uint8Codec{}, nil
|
||||
case reflect.Uint16:
|
||||
return &uint16Codec{}, nil
|
||||
case reflect.Uint32:
|
||||
return &uint32Codec{}, nil
|
||||
case reflect.Uintptr:
|
||||
return &uintptrCodec{}, nil
|
||||
case reflect.Uint64:
|
||||
return &uint64Codec{}, nil
|
||||
case reflect.Float32:
|
||||
return &float32Codec{}, nil
|
||||
case reflect.Float64:
|
||||
return &float64Codec{}, nil
|
||||
case reflect.Bool:
|
||||
return &boolCodec{}, nil
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return &structEncoder{}, nil
|
||||
case reflect.Array:
|
||||
return &arrayEncoder{}, nil
|
||||
case reflect.Slice:
|
||||
return &sliceEncoder{}, nil
|
||||
case reflect.Map:
|
||||
return &mapEncoder{}, nil
|
||||
case reflect.Ptr:
|
||||
return &optionalEncoder{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type: %v", typ)
|
||||
}
|
||||
}
|
||||
|
||||
func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
typeName := typ.String()
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
if typeName != "string" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
|
||||
}
|
||||
return &stringCodec{}, nil
|
||||
case reflect.Int:
|
||||
if typeName != "int" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
|
||||
}
|
||||
return &intCodec{}, nil
|
||||
case reflect.Int8:
|
||||
if typeName != "int8" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
}
|
||||
return &int8Codec{}, nil
|
||||
case reflect.Int16:
|
||||
if typeName != "int16" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
}
|
||||
return &int16Codec{}, nil
|
||||
case reflect.Int32:
|
||||
if typeName != "int32" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
}
|
||||
return &int32Codec{}, nil
|
||||
case reflect.Int64:
|
||||
if typeName != "int64" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
}
|
||||
return &int64Codec{}, nil
|
||||
case reflect.Uint:
|
||||
if typeName != "uint" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
}
|
||||
return &uintCodec{}, nil
|
||||
case reflect.Uint8:
|
||||
if typeName != "uint8" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
}
|
||||
return &uint8Codec{}, nil
|
||||
case reflect.Uint16:
|
||||
if typeName != "uint16" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
}
|
||||
return &uint16Codec{}, nil
|
||||
case reflect.Uint32:
|
||||
if typeName != "uint32" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
}
|
||||
return &uint32Codec{}, nil
|
||||
case reflect.Uintptr:
|
||||
if typeName != "uintptr" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
}
|
||||
return &uintptrCodec{}, nil
|
||||
case reflect.Uint64:
|
||||
if typeName != "uint64" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
}
|
||||
return &uint64Codec{}, nil
|
||||
case reflect.Float32:
|
||||
if typeName != "float32" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
}
|
||||
return &float32Codec{}, nil
|
||||
case reflect.Float64:
|
||||
if typeName != "float64" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
}
|
||||
return &float64Codec{}, nil
|
||||
case reflect.Bool:
|
||||
if typeName != "bool" {
|
||||
return encoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
}
|
||||
return &boolCodec{}, nil
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
|
||||
case reflect.Array:
|
||||
return prefix("[array]").addToEncoder(encoderOfArray(cfg, typ))
|
||||
case reflect.Slice:
|
||||
return prefix("[slice]").addToEncoder(encoderOfSlice(cfg, typ))
|
||||
case reflect.Map:
|
||||
return prefix("[map]").addToEncoder(encoderOfMap(cfg, typ))
|
||||
case reflect.Ptr:
|
||||
return prefix("[optional]").addToEncoder(encoderOfOptional(cfg, typ))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type: %v", typ)
|
||||
}
|
||||
}
|
||||
|
||||
func decoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
elemType := typ.Elem()
|
||||
decoder, err := decoderOfType(cfg, elemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &optionalDecoder{elemType, decoder}, nil
|
||||
}
|
||||
|
||||
func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
elemType := typ.Elem()
|
||||
elemEncoder, err := encoderOfType(cfg, elemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encoder := &optionalEncoder{elemEncoder}
|
||||
if elemType.Kind() == reflect.Map {
|
||||
encoder = &optionalEncoder{encoder}
|
||||
}
|
||||
return encoder, nil
|
||||
}
|
||||
|
||||
func decoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
decoder, err := decoderOfType(cfg, typ.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapInterface := reflect.New(typ).Interface()
|
||||
return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}, nil
|
||||
}
|
||||
|
||||
func extractInterface(val interface{}) emptyInterface {
|
||||
return *((*emptyInterface)(unsafe.Pointer(&val)))
|
||||
}
|
||||
|
||||
func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
elemType := typ.Elem()
|
||||
encoder, err := encoderOfType(cfg, elemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapInterface := reflect.New(typ).Elem().Interface()
|
||||
if cfg.sortMapKeys {
|
||||
return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||
}
|
||||
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||
}
|
||||
99
vendor/github.com/json-iterator/go/feature_reflect_array.go
generated
vendored
99
vendor/github.com/json-iterator/go/feature_reflect_array.go
generated
vendored
@@ -1,99 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
decoder, err := decoderOfType(cfg, typ.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &arrayDecoder{typ, typ.Elem(), decoder}, nil
|
||||
}
|
||||
|
||||
func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
encoder, err := encoderOfType(cfg, typ.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if typ.Elem().Kind() == reflect.Map {
|
||||
encoder = &optionalEncoder{encoder}
|
||||
}
|
||||
return &arrayEncoder{typ, typ.Elem(), encoder}, nil
|
||||
}
|
||||
|
||||
type arrayEncoder struct {
|
||||
arrayType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemEncoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteArrayStart()
|
||||
elemPtr := unsafe.Pointer(ptr)
|
||||
encoder.elemEncoder.Encode(elemPtr, stream)
|
||||
for i := 1; i < encoder.arrayType.Len(); i++ {
|
||||
stream.WriteMore()
|
||||
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
|
||||
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
|
||||
}
|
||||
stream.WriteArrayEnd()
|
||||
if stream.Error != nil && stream.Error != io.EOF {
|
||||
stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *arrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
// special optimization for interface{}
|
||||
e := (*emptyInterface)(unsafe.Pointer(&val))
|
||||
if e.word == nil {
|
||||
stream.WriteArrayStart()
|
||||
stream.WriteNil()
|
||||
stream.WriteArrayEnd()
|
||||
return
|
||||
}
|
||||
elemType := encoder.arrayType.Elem()
|
||||
if encoder.arrayType.Len() == 1 && (elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map) {
|
||||
ptr := uintptr(e.word)
|
||||
e.word = unsafe.Pointer(&ptr)
|
||||
}
|
||||
if reflect.TypeOf(val).Kind() == reflect.Ptr {
|
||||
encoder.Encode(unsafe.Pointer(&e.word), stream)
|
||||
} else {
|
||||
encoder.Encode(e.word, stream)
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type arrayDecoder struct {
|
||||
arrayType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.doDecode(ptr, iter)
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
offset := uintptr(0)
|
||||
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||
if offset < decoder.arrayType.Size() {
|
||||
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(ptr)+offset), iter)
|
||||
offset += decoder.elemType.Size()
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
244
vendor/github.com/json-iterator/go/feature_reflect_map.go
generated
vendored
244
vendor/github.com/json-iterator/go/feature_reflect_map.go
generated
vendored
@@ -1,244 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType reflect.Type
|
||||
keyType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemDecoder ValDecoder
|
||||
mapInterface emptyInterface
|
||||
}
|
||||
|
||||
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
// dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
|
||||
mapInterface := decoder.mapInterface
|
||||
mapInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
||||
realVal := reflect.ValueOf(*realInterface).Elem()
|
||||
if iter.ReadNil() {
|
||||
realVal.Set(reflect.Zero(decoder.mapType))
|
||||
return
|
||||
}
|
||||
if realVal.IsNil() {
|
||||
realVal.Set(reflect.MakeMap(realVal.Type()))
|
||||
}
|
||||
iter.ReadMapCB(func(iter *Iterator, keyStr string) bool {
|
||||
elem := reflect.New(decoder.elemType)
|
||||
decoder.elemDecoder.Decode(unsafe.Pointer(elem.Pointer()), iter)
|
||||
// to put into map, we have to use reflection
|
||||
keyType := decoder.keyType
|
||||
// TODO: remove this from loop
|
||||
switch {
|
||||
case keyType.Kind() == reflect.String:
|
||||
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
|
||||
return true
|
||||
case keyType.Implements(textUnmarshalerType):
|
||||
textUnmarshaler := reflect.New(keyType.Elem()).Interface().(encoding.TextUnmarshaler)
|
||||
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
|
||||
if err != nil {
|
||||
iter.ReportError("read map key as TextUnmarshaler", err.Error())
|
||||
return false
|
||||
}
|
||||
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
|
||||
return true
|
||||
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
|
||||
textUnmarshaler := reflect.New(keyType).Interface().(encoding.TextUnmarshaler)
|
||||
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
|
||||
if err != nil {
|
||||
iter.ReportError("read map key as TextUnmarshaler", err.Error())
|
||||
return false
|
||||
}
|
||||
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler).Elem(), elem.Elem())
|
||||
return true
|
||||
default:
|
||||
switch keyType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n, err := strconv.ParseInt(keyStr, 10, 64)
|
||||
if err != nil || reflect.Zero(keyType).OverflowInt(n) {
|
||||
iter.ReportError("read map key as int64", "read int64 failed")
|
||||
return false
|
||||
}
|
||||
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
|
||||
return true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n, err := strconv.ParseUint(keyStr, 10, 64)
|
||||
if err != nil || reflect.Zero(keyType).OverflowUint(n) {
|
||||
iter.ReportError("read map key as uint64", "read uint64 failed")
|
||||
return false
|
||||
}
|
||||
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
|
||||
return true
|
||||
}
|
||||
}
|
||||
iter.ReportError("read map key", "unexpected map key type "+keyType.String())
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
type mapEncoder struct {
|
||||
mapType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemEncoder ValEncoder
|
||||
mapInterface emptyInterface
|
||||
}
|
||||
|
||||
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
mapInterface := encoder.mapInterface
|
||||
mapInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
||||
realVal := reflect.ValueOf(*realInterface)
|
||||
stream.WriteObjectStart()
|
||||
for i, key := range realVal.MapKeys() {
|
||||
if i != 0 {
|
||||
stream.WriteMore()
|
||||
}
|
||||
encodeMapKey(key, stream)
|
||||
if stream.indention > 0 {
|
||||
stream.writeTwoBytes(byte(':'), byte(' '))
|
||||
} else {
|
||||
stream.writeByte(':')
|
||||
}
|
||||
val := realVal.MapIndex(key).Interface()
|
||||
encoder.elemEncoder.EncodeInterface(val, stream)
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
}
|
||||
|
||||
func encodeMapKey(key reflect.Value, stream *Stream) {
|
||||
if key.Kind() == reflect.String {
|
||||
stream.WriteString(key.String())
|
||||
return
|
||||
}
|
||||
if tm, ok := key.Interface().(encoding.TextMarshaler); ok {
|
||||
buf, err := tm.MarshalText()
|
||||
if err != nil {
|
||||
stream.Error = err
|
||||
return
|
||||
}
|
||||
stream.writeByte('"')
|
||||
stream.Write(buf)
|
||||
stream.writeByte('"')
|
||||
return
|
||||
}
|
||||
switch key.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
stream.writeByte('"')
|
||||
stream.WriteInt64(key.Int())
|
||||
stream.writeByte('"')
|
||||
return
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
stream.writeByte('"')
|
||||
stream.WriteUint64(key.Uint())
|
||||
stream.writeByte('"')
|
||||
return
|
||||
}
|
||||
stream.Error = &json.UnsupportedTypeError{Type: key.Type()}
|
||||
}
|
||||
|
||||
func (encoder *mapEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
mapInterface := encoder.mapInterface
|
||||
mapInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
||||
realVal := reflect.ValueOf(*realInterface)
|
||||
return realVal.Len() == 0
|
||||
}
|
||||
|
||||
type sortKeysMapEncoder struct {
|
||||
mapType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemEncoder ValEncoder
|
||||
mapInterface emptyInterface
|
||||
}
|
||||
|
||||
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
mapInterface := encoder.mapInterface
|
||||
mapInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
||||
realVal := reflect.ValueOf(*realInterface)
|
||||
|
||||
// Extract and sort the keys.
|
||||
keys := realVal.MapKeys()
|
||||
sv := stringValues(make([]reflectWithString, len(keys)))
|
||||
for i, v := range keys {
|
||||
sv[i].v = v
|
||||
if err := sv[i].resolve(); err != nil {
|
||||
stream.Error = err
|
||||
return
|
||||
}
|
||||
}
|
||||
sort.Sort(sv)
|
||||
|
||||
stream.WriteObjectStart()
|
||||
for i, key := range sv {
|
||||
if i != 0 {
|
||||
stream.WriteMore()
|
||||
}
|
||||
stream.WriteVal(key.s) // might need html escape, so can not WriteString directly
|
||||
if stream.indention > 0 {
|
||||
stream.writeTwoBytes(byte(':'), byte(' '))
|
||||
} else {
|
||||
stream.writeByte(':')
|
||||
}
|
||||
val := realVal.MapIndex(key.v).Interface()
|
||||
encoder.elemEncoder.EncodeInterface(val, stream)
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
}
|
||||
|
||||
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
||||
// It implements the methods to sort by string.
|
||||
type stringValues []reflectWithString
|
||||
|
||||
type reflectWithString struct {
|
||||
v reflect.Value
|
||||
s string
|
||||
}
|
||||
|
||||
func (w *reflectWithString) resolve() error {
|
||||
if w.v.Kind() == reflect.String {
|
||||
w.s = w.v.String()
|
||||
return nil
|
||||
}
|
||||
if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
|
||||
buf, err := tm.MarshalText()
|
||||
w.s = string(buf)
|
||||
return err
|
||||
}
|
||||
switch w.v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
w.s = strconv.FormatInt(w.v.Int(), 10)
|
||||
return nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
w.s = strconv.FormatUint(w.v.Uint(), 10)
|
||||
return nil
|
||||
}
|
||||
return &json.UnsupportedTypeError{Type: w.v.Type()}
|
||||
}
|
||||
|
||||
func (sv stringValues) Len() int { return len(sv) }
|
||||
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
||||
func (sv stringValues) Less(i, j int) bool { return sv[i].s < sv[j].s }
|
||||
|
||||
func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
mapInterface := encoder.mapInterface
|
||||
mapInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
|
||||
realVal := reflect.ValueOf(*realInterface)
|
||||
return realVal.Len() == 0
|
||||
}
|
||||
672
vendor/github.com/json-iterator/go/feature_reflect_native.go
generated
vendored
672
vendor/github.com/json-iterator/go/feature_reflect_native.go
generated
vendored
@@ -1,672 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type stringCodec struct {
|
||||
}
|
||||
|
||||
func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*string)(ptr)) = iter.ReadString()
|
||||
}
|
||||
|
||||
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
str := *((*string)(ptr))
|
||||
stream.WriteString(str)
|
||||
}
|
||||
|
||||
func (codec *stringCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*string)(ptr)) == ""
|
||||
}
|
||||
|
||||
type intCodec struct {
|
||||
}
|
||||
|
||||
func (codec *intCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*int)(ptr)) = iter.ReadInt()
|
||||
}
|
||||
|
||||
func (codec *intCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteInt(*((*int)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *intCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *intCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*int)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uintptrCodec struct {
|
||||
}
|
||||
|
||||
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
|
||||
}
|
||||
|
||||
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
|
||||
}
|
||||
|
||||
func (codec *uintptrCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uintptrCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uintptr)(ptr)) == 0
|
||||
}
|
||||
|
||||
type int8Codec struct {
|
||||
}
|
||||
|
||||
func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*int8)(ptr)) = iter.ReadInt8()
|
||||
}
|
||||
|
||||
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteInt8(*((*int8)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *int8Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*int8)(ptr)) == 0
|
||||
}
|
||||
|
||||
type int16Codec struct {
|
||||
}
|
||||
|
||||
func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*int16)(ptr)) = iter.ReadInt16()
|
||||
}
|
||||
|
||||
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteInt16(*((*int16)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *int16Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*int16)(ptr)) == 0
|
||||
}
|
||||
|
||||
type int32Codec struct {
|
||||
}
|
||||
|
||||
func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*int32)(ptr)) = iter.ReadInt32()
|
||||
}
|
||||
|
||||
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteInt32(*((*int32)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *int32Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*int32)(ptr)) == 0
|
||||
}
|
||||
|
||||
type int64Codec struct {
|
||||
}
|
||||
|
||||
func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*int64)(ptr)) = iter.ReadInt64()
|
||||
}
|
||||
|
||||
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteInt64(*((*int64)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *int64Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*int64)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uintCodec struct {
|
||||
}
|
||||
|
||||
func (codec *uintCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uint)(ptr)) = iter.ReadUint()
|
||||
}
|
||||
|
||||
func (codec *uintCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint(*((*uint)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *uintCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uintCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uint)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uint8Codec struct {
|
||||
}
|
||||
|
||||
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uint8)(ptr)) = iter.ReadUint8()
|
||||
}
|
||||
|
||||
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint8(*((*uint8)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *uint8Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uint8)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uint16Codec struct {
|
||||
}
|
||||
|
||||
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uint16)(ptr)) = iter.ReadUint16()
|
||||
}
|
||||
|
||||
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint16(*((*uint16)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *uint16Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uint16)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uint32Codec struct {
|
||||
}
|
||||
|
||||
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uint32)(ptr)) = iter.ReadUint32()
|
||||
}
|
||||
|
||||
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint32(*((*uint32)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *uint32Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uint32)(ptr)) == 0
|
||||
}
|
||||
|
||||
type uint64Codec struct {
|
||||
}
|
||||
|
||||
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*uint64)(ptr)) = iter.ReadUint64()
|
||||
}
|
||||
|
||||
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteUint64(*((*uint64)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *uint64Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*uint64)(ptr)) == 0
|
||||
}
|
||||
|
||||
type float32Codec struct {
|
||||
}
|
||||
|
||||
func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*float32)(ptr)) = iter.ReadFloat32()
|
||||
}
|
||||
|
||||
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat32(*((*float32)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *float32Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float32)(ptr)) == 0
|
||||
}
|
||||
|
||||
type float64Codec struct {
|
||||
}
|
||||
|
||||
func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*float64)(ptr)) = iter.ReadFloat64()
|
||||
}
|
||||
|
||||
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteFloat64(*((*float64)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *float64Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*float64)(ptr)) == 0
|
||||
}
|
||||
|
||||
type boolCodec struct {
|
||||
}
|
||||
|
||||
func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*bool)(ptr)) = iter.ReadBool()
|
||||
}
|
||||
|
||||
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteBool(*((*bool)(ptr)))
|
||||
}
|
||||
|
||||
func (codec *boolCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, codec)
|
||||
}
|
||||
|
||||
func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return !(*((*bool)(ptr)))
|
||||
}
|
||||
|
||||
type emptyInterfaceCodec struct {
|
||||
}
|
||||
|
||||
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*interface{})(ptr)) = iter.Read()
|
||||
}
|
||||
|
||||
func (codec *emptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteVal(*((*interface{})(ptr)))
|
||||
}
|
||||
|
||||
func (codec *emptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteVal(val)
|
||||
}
|
||||
|
||||
func (codec *emptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return ptr == nil
|
||||
}
|
||||
|
||||
type nonEmptyInterfaceCodec struct {
|
||||
}
|
||||
|
||||
func (codec *nonEmptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
nonEmptyInterface := (*nonEmptyInterface)(ptr)
|
||||
if nonEmptyInterface.itab == nil {
|
||||
iter.ReportError("read non-empty interface", "do not know which concrete type to decode to")
|
||||
return
|
||||
}
|
||||
var i interface{}
|
||||
e := (*emptyInterface)(unsafe.Pointer(&i))
|
||||
e.typ = nonEmptyInterface.itab.typ
|
||||
e.word = nonEmptyInterface.word
|
||||
iter.ReadVal(&i)
|
||||
nonEmptyInterface.word = e.word
|
||||
}
|
||||
|
||||
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
nonEmptyInterface := (*nonEmptyInterface)(ptr)
|
||||
var i interface{}
|
||||
e := (*emptyInterface)(unsafe.Pointer(&i))
|
||||
e.typ = nonEmptyInterface.itab.typ
|
||||
e.word = nonEmptyInterface.word
|
||||
stream.WriteVal(i)
|
||||
}
|
||||
|
||||
func (codec *nonEmptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteVal(val)
|
||||
}
|
||||
|
||||
func (codec *nonEmptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
nonEmptyInterface := (*nonEmptyInterface)(ptr)
|
||||
return nonEmptyInterface.word == nil
|
||||
}
|
||||
|
||||
type anyCodec struct {
|
||||
}
|
||||
|
||||
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*Any)(ptr)) = iter.ReadAny()
|
||||
}
|
||||
|
||||
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
(*((*Any)(ptr))).WriteTo(stream)
|
||||
}
|
||||
|
||||
func (codec *anyCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
(val.(Any)).WriteTo(stream)
|
||||
}
|
||||
|
||||
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return (*((*Any)(ptr))).Size() == 0
|
||||
}
|
||||
|
||||
type jsonNumberCodec struct {
|
||||
}
|
||||
|
||||
func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString()))
|
||||
}
|
||||
|
||||
func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteRaw(string(*((*json.Number)(ptr))))
|
||||
}
|
||||
|
||||
func (codec *jsonNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteRaw(string(val.(json.Number)))
|
||||
}
|
||||
|
||||
func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return len(*((*json.Number)(ptr))) == 0
|
||||
}
|
||||
|
||||
type jsoniterNumberCodec struct {
|
||||
}
|
||||
|
||||
func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*Number)(ptr)) = Number([]byte(iter.readNumberAsString()))
|
||||
}
|
||||
|
||||
func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteRaw(string(*((*Number)(ptr))))
|
||||
}
|
||||
|
||||
func (codec *jsoniterNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteRaw(string(val.(Number)))
|
||||
}
|
||||
|
||||
func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return len(*((*Number)(ptr))) == 0
|
||||
}
|
||||
|
||||
type jsonRawMessageCodec struct {
|
||||
}
|
||||
|
||||
func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
|
||||
}
|
||||
|
||||
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
|
||||
}
|
||||
|
||||
func (codec *jsonRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteRaw(string(val.(json.RawMessage)))
|
||||
}
|
||||
|
||||
func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return len(*((*json.RawMessage)(ptr))) == 0
|
||||
}
|
||||
|
||||
type jsoniterRawMessageCodec struct {
|
||||
}
|
||||
|
||||
func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
|
||||
}
|
||||
|
||||
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteRaw(string(*((*RawMessage)(ptr))))
|
||||
}
|
||||
|
||||
func (codec *jsoniterRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
stream.WriteRaw(string(val.(RawMessage)))
|
||||
}
|
||||
|
||||
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return len(*((*RawMessage)(ptr))) == 0
|
||||
}
|
||||
|
||||
type base64Codec struct {
|
||||
sliceDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.ReadNil() {
|
||||
ptrSlice := (*sliceHeader)(ptr)
|
||||
ptrSlice.Len = 0
|
||||
ptrSlice.Cap = 0
|
||||
ptrSlice.Data = nil
|
||||
return
|
||||
}
|
||||
switch iter.WhatIsNext() {
|
||||
case StringValue:
|
||||
encoding := base64.StdEncoding
|
||||
src := iter.SkipAndReturnBytes()
|
||||
src = src[1 : len(src)-1]
|
||||
decodedLen := encoding.DecodedLen(len(src))
|
||||
dst := make([]byte, decodedLen)
|
||||
len, err := encoding.Decode(dst, src)
|
||||
if err != nil {
|
||||
iter.ReportError("decode base64", err.Error())
|
||||
} else {
|
||||
dst = dst[:len]
|
||||
dstSlice := (*sliceHeader)(unsafe.Pointer(&dst))
|
||||
ptrSlice := (*sliceHeader)(ptr)
|
||||
ptrSlice.Data = dstSlice.Data
|
||||
ptrSlice.Cap = dstSlice.Cap
|
||||
ptrSlice.Len = dstSlice.Len
|
||||
}
|
||||
case ArrayValue:
|
||||
codec.sliceDecoder.Decode(ptr, iter)
|
||||
default:
|
||||
iter.ReportError("base64Codec", "invalid input")
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
src := *((*[]byte)(ptr))
|
||||
if len(src) == 0 {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
encoding := base64.StdEncoding
|
||||
stream.writeByte('"')
|
||||
toGrow := encoding.EncodedLen(len(src))
|
||||
stream.ensure(toGrow)
|
||||
encoding.Encode(stream.buf[stream.n:], src)
|
||||
stream.n += toGrow
|
||||
stream.writeByte('"')
|
||||
}
|
||||
|
||||
func (codec *base64Codec) EncodeInterface(val interface{}, stream *Stream) {
|
||||
ptr := extractInterface(val).word
|
||||
src := *((*[]byte)(ptr))
|
||||
if len(src) == 0 {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
encoding := base64.StdEncoding
|
||||
stream.writeByte('"')
|
||||
toGrow := encoding.EncodedLen(len(src))
|
||||
stream.ensure(toGrow)
|
||||
encoding.Encode(stream.buf[stream.n:], src)
|
||||
stream.n += toGrow
|
||||
stream.writeByte('"')
|
||||
}
|
||||
|
||||
func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return len(*((*[]byte)(ptr))) == 0
|
||||
}
|
||||
|
||||
type stringModeNumberDecoder struct {
|
||||
elemDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
c := iter.nextToken()
|
||||
if c != '"' {
|
||||
iter.ReportError("stringModeNumberDecoder", `expect "`)
|
||||
return
|
||||
}
|
||||
decoder.elemDecoder.Decode(ptr, iter)
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
c = iter.readByte()
|
||||
if c != '"' {
|
||||
iter.ReportError("stringModeNumberDecoder", `expect "`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type stringModeStringDecoder struct {
|
||||
elemDecoder ValDecoder
|
||||
cfg *frozenConfig
|
||||
}
|
||||
|
||||
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.elemDecoder.Decode(ptr, iter)
|
||||
str := *((*string)(ptr))
|
||||
tempIter := decoder.cfg.BorrowIterator([]byte(str))
|
||||
defer decoder.cfg.ReturnIterator(tempIter)
|
||||
*((*string)(ptr)) = tempIter.ReadString()
|
||||
}
|
||||
|
||||
type stringModeNumberEncoder struct {
|
||||
elemEncoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.writeByte('"')
|
||||
encoder.elemEncoder.Encode(ptr, stream)
|
||||
stream.writeByte('"')
|
||||
}
|
||||
|
||||
func (encoder *stringModeNumberEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.elemEncoder.IsEmpty(ptr)
|
||||
}
|
||||
|
||||
type stringModeStringEncoder struct {
|
||||
elemEncoder ValEncoder
|
||||
cfg *frozenConfig
|
||||
}
|
||||
|
||||
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
tempStream := encoder.cfg.BorrowStream(nil)
|
||||
defer encoder.cfg.ReturnStream(tempStream)
|
||||
encoder.elemEncoder.Encode(ptr, tempStream)
|
||||
stream.WriteString(string(tempStream.Buffer()))
|
||||
}
|
||||
|
||||
func (encoder *stringModeStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.elemEncoder.IsEmpty(ptr)
|
||||
}
|
||||
|
||||
type marshalerEncoder struct {
|
||||
templateInterface emptyInterface
|
||||
checkIsEmpty checkIsEmpty
|
||||
}
|
||||
|
||||
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
templateInterface := encoder.templateInterface
|
||||
templateInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||
marshaler := (*realInterface).(json.Marshaler)
|
||||
bytes, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
stream.Error = err
|
||||
} else {
|
||||
stream.Write(bytes)
|
||||
}
|
||||
}
|
||||
func (encoder *marshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.checkIsEmpty.IsEmpty(ptr)
|
||||
}
|
||||
|
||||
type textMarshalerEncoder struct {
|
||||
templateInterface emptyInterface
|
||||
checkIsEmpty checkIsEmpty
|
||||
}
|
||||
|
||||
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
templateInterface := encoder.templateInterface
|
||||
templateInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||
marshaler := (*realInterface).(encoding.TextMarshaler)
|
||||
bytes, err := marshaler.MarshalText()
|
||||
if err != nil {
|
||||
stream.Error = err
|
||||
} else {
|
||||
stream.WriteString(string(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *textMarshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.checkIsEmpty.IsEmpty(ptr)
|
||||
}
|
||||
|
||||
type unmarshalerDecoder struct {
|
||||
templateInterface emptyInterface
|
||||
}
|
||||
|
||||
func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
templateInterface := decoder.templateInterface
|
||||
templateInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||
unmarshaler := (*realInterface).(json.Unmarshaler)
|
||||
iter.nextToken()
|
||||
iter.unreadByte() // skip spaces
|
||||
bytes := iter.SkipAndReturnBytes()
|
||||
err := unmarshaler.UnmarshalJSON(bytes)
|
||||
if err != nil {
|
||||
iter.ReportError("unmarshalerDecoder", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type textUnmarshalerDecoder struct {
|
||||
templateInterface emptyInterface
|
||||
}
|
||||
|
||||
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
templateInterface := decoder.templateInterface
|
||||
templateInterface.word = ptr
|
||||
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||
unmarshaler := (*realInterface).(encoding.TextUnmarshaler)
|
||||
str := iter.ReadString()
|
||||
err := unmarshaler.UnmarshalText([]byte(str))
|
||||
if err != nil {
|
||||
iter.ReportError("textUnmarshalerDecoder", err.Error())
|
||||
}
|
||||
}
|
||||
149
vendor/github.com/json-iterator/go/feature_reflect_slice.go
generated
vendored
149
vendor/github.com/json-iterator/go/feature_reflect_slice.go
generated
vendored
@@ -1,149 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
||||
decoder, err := decoderOfType(cfg, typ.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
|
||||
}
|
||||
|
||||
func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
encoder, err := encoderOfType(cfg, typ.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if typ.Elem().Kind() == reflect.Map {
|
||||
encoder = &optionalEncoder{encoder}
|
||||
}
|
||||
return &sliceEncoder{typ, typ.Elem(), encoder}, nil
|
||||
}
|
||||
|
||||
type sliceEncoder struct {
|
||||
sliceType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemEncoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
slice := (*sliceHeader)(ptr)
|
||||
if slice.Data == nil {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
if slice.Len == 0 {
|
||||
stream.WriteEmptyArray()
|
||||
return
|
||||
}
|
||||
stream.WriteArrayStart()
|
||||
elemPtr := unsafe.Pointer(slice.Data)
|
||||
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
|
||||
for i := 1; i < slice.Len; i++ {
|
||||
stream.WriteMore()
|
||||
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
|
||||
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
|
||||
}
|
||||
stream.WriteArrayEnd()
|
||||
if stream.Error != nil && stream.Error != io.EOF {
|
||||
stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *sliceEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||
WriteToStream(val, stream, encoder)
|
||||
}
|
||||
|
||||
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
slice := (*sliceHeader)(ptr)
|
||||
return slice.Len == 0
|
||||
}
|
||||
|
||||
type sliceDecoder struct {
|
||||
sliceType reflect.Type
|
||||
elemType reflect.Type
|
||||
elemDecoder ValDecoder
|
||||
}
|
||||
|
||||
// sliceHeader is a safe version of SliceHeader used within this package.
|
||||
type sliceHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.doDecode(ptr, iter)
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
slice := (*sliceHeader)(ptr)
|
||||
if iter.ReadNil() {
|
||||
slice.Len = 0
|
||||
slice.Cap = 0
|
||||
slice.Data = nil
|
||||
return
|
||||
}
|
||||
reuseSlice(slice, decoder.sliceType, 4)
|
||||
slice.Len = 0
|
||||
offset := uintptr(0)
|
||||
iter.ReadArrayCB(func(iter *Iterator) bool {
|
||||
growOne(slice, decoder.sliceType, decoder.elemType)
|
||||
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
|
||||
offset += decoder.elemType.Size()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// grow grows the slice s so that it can hold extra more values, allocating
|
||||
// more capacity if needed. It also returns the old and new slice lengths.
|
||||
func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
|
||||
newLen := slice.Len + 1
|
||||
if newLen <= slice.Cap {
|
||||
slice.Len = newLen
|
||||
return
|
||||
}
|
||||
newCap := slice.Cap
|
||||
if newCap == 0 {
|
||||
newCap = 1
|
||||
} else {
|
||||
for newCap < newLen {
|
||||
if slice.Len < 1024 {
|
||||
newCap += newCap
|
||||
} else {
|
||||
newCap += newCap / 4
|
||||
}
|
||||
}
|
||||
}
|
||||
newVal := reflect.MakeSlice(sliceType, newLen, newCap)
|
||||
dst := unsafe.Pointer(newVal.Pointer())
|
||||
// copy old array into new array
|
||||
originalBytesCount := uintptr(slice.Len) * elementType.Size()
|
||||
srcPtr := (*[1 << 30]byte)(slice.Data)
|
||||
dstPtr := (*[1 << 30]byte)(dst)
|
||||
for i := uintptr(0); i < originalBytesCount; i++ {
|
||||
dstPtr[i] = srcPtr[i]
|
||||
}
|
||||
slice.Data = dst
|
||||
slice.Len = newLen
|
||||
slice.Cap = newCap
|
||||
}
|
||||
|
||||
func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
|
||||
if expectedCap <= slice.Cap {
|
||||
return
|
||||
}
|
||||
newVal := reflect.MakeSlice(sliceType, 0, expectedCap)
|
||||
dst := unsafe.Pointer(newVal.Pointer())
|
||||
slice.Data = dst
|
||||
slice.Cap = expectedCap
|
||||
}
|
||||
320
vendor/github.com/json-iterator/go/feature_stream_int.go
generated
vendored
320
vendor/github.com/json-iterator/go/feature_stream_int.go
generated
vendored
@@ -1,320 +0,0 @@
|
||||
package jsoniter
|
||||
|
||||
var digits []uint32
|
||||
|
||||
func init() {
|
||||
digits = make([]uint32, 1000)
|
||||
for i := uint32(0); i < 1000; i++ {
|
||||
digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0'
|
||||
if i < 10 {
|
||||
digits[i] += 2 << 24
|
||||
} else if i < 100 {
|
||||
digits[i] += 1 << 24
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writeFirstBuf(buf []byte, v uint32, n int) int {
|
||||
start := v >> 24
|
||||
if start == 0 {
|
||||
buf[n] = byte(v >> 16)
|
||||
n++
|
||||
buf[n] = byte(v >> 8)
|
||||
n++
|
||||
} else if start == 1 {
|
||||
buf[n] = byte(v >> 8)
|
||||
n++
|
||||
}
|
||||
buf[n] = byte(v)
|
||||
n++
|
||||
return n
|
||||
}
|
||||
|
||||
func writeBuf(buf []byte, v uint32, n int) {
|
||||
buf[n] = byte(v >> 16)
|
||||
buf[n+1] = byte(v >> 8)
|
||||
buf[n+2] = byte(v)
|
||||
}
|
||||
|
||||
// WriteUint8 write uint8 to stream
|
||||
func (stream *Stream) WriteUint8(val uint8) {
|
||||
stream.ensure(3)
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
|
||||
}
|
||||
|
||||
// WriteInt8 write int8 to stream
|
||||
func (stream *Stream) WriteInt8(nval int8) {
|
||||
stream.ensure(4)
|
||||
n := stream.n
|
||||
var val uint8
|
||||
if nval < 0 {
|
||||
val = uint8(-nval)
|
||||
stream.buf[n] = '-'
|
||||
n++
|
||||
} else {
|
||||
val = uint8(nval)
|
||||
}
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
}
|
||||
|
||||
// WriteUint16 write uint16 to stream
|
||||
func (stream *Stream) WriteUint16(val uint16) {
|
||||
stream.ensure(5)
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
n := writeFirstBuf(stream.buf, digits[q1], stream.n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
|
||||
// WriteInt16 write int16 to stream
|
||||
func (stream *Stream) WriteInt16(nval int16) {
|
||||
stream.ensure(6)
|
||||
n := stream.n
|
||||
var val uint16
|
||||
if nval < 0 {
|
||||
val = uint16(-nval)
|
||||
stream.buf[n] = '-'
|
||||
n++
|
||||
} else {
|
||||
val = uint16(nval)
|
||||
}
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
n = writeFirstBuf(stream.buf, digits[q1], n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
|
||||
// WriteUint32 write uint32 to stream
|
||||
func (stream *Stream) WriteUint32(val uint32) {
|
||||
stream.ensure(10)
|
||||
n := stream.n
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
q2 := q1 / 1000
|
||||
if q2 == 0 {
|
||||
n := writeFirstBuf(stream.buf, digits[q1], n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
r2 := q1 - q2*1000
|
||||
q3 := q2 / 1000
|
||||
if q3 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q2], n)
|
||||
} else {
|
||||
r3 := q2 - q3*1000
|
||||
stream.buf[n] = byte(q3 + '0')
|
||||
n++
|
||||
writeBuf(stream.buf, digits[r3], n)
|
||||
n += 3
|
||||
}
|
||||
writeBuf(stream.buf, digits[r2], n)
|
||||
writeBuf(stream.buf, digits[r1], n+3)
|
||||
stream.n = n + 6
|
||||
}
|
||||
|
||||
// WriteInt32 write int32 to stream
|
||||
func (stream *Stream) WriteInt32(nval int32) {
|
||||
stream.ensure(11)
|
||||
n := stream.n
|
||||
var val uint32
|
||||
if nval < 0 {
|
||||
val = uint32(-nval)
|
||||
stream.buf[n] = '-'
|
||||
n++
|
||||
} else {
|
||||
val = uint32(nval)
|
||||
}
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
q2 := q1 / 1000
|
||||
if q2 == 0 {
|
||||
n := writeFirstBuf(stream.buf, digits[q1], n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
r2 := q1 - q2*1000
|
||||
q3 := q2 / 1000
|
||||
if q3 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q2], n)
|
||||
} else {
|
||||
r3 := q2 - q3*1000
|
||||
stream.buf[n] = byte(q3 + '0')
|
||||
n++
|
||||
writeBuf(stream.buf, digits[r3], n)
|
||||
n += 3
|
||||
}
|
||||
writeBuf(stream.buf, digits[r2], n)
|
||||
writeBuf(stream.buf, digits[r1], n+3)
|
||||
stream.n = n + 6
|
||||
}
|
||||
|
||||
// WriteUint64 write uint64 to stream
|
||||
func (stream *Stream) WriteUint64(val uint64) {
|
||||
stream.ensure(20)
|
||||
n := stream.n
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
q2 := q1 / 1000
|
||||
if q2 == 0 {
|
||||
n := writeFirstBuf(stream.buf, digits[q1], n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
r2 := q1 - q2*1000
|
||||
q3 := q2 / 1000
|
||||
if q3 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q2], n)
|
||||
writeBuf(stream.buf, digits[r2], n)
|
||||
writeBuf(stream.buf, digits[r1], n+3)
|
||||
stream.n = n + 6
|
||||
return
|
||||
}
|
||||
r3 := q2 - q3*1000
|
||||
q4 := q3 / 1000
|
||||
if q4 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q3], n)
|
||||
writeBuf(stream.buf, digits[r3], n)
|
||||
writeBuf(stream.buf, digits[r2], n+3)
|
||||
writeBuf(stream.buf, digits[r1], n+6)
|
||||
stream.n = n + 9
|
||||
return
|
||||
}
|
||||
r4 := q3 - q4*1000
|
||||
q5 := q4 / 1000
|
||||
if q5 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q4], n)
|
||||
writeBuf(stream.buf, digits[r4], n)
|
||||
writeBuf(stream.buf, digits[r3], n+3)
|
||||
writeBuf(stream.buf, digits[r2], n+6)
|
||||
writeBuf(stream.buf, digits[r1], n+9)
|
||||
stream.n = n + 12
|
||||
return
|
||||
}
|
||||
r5 := q4 - q5*1000
|
||||
q6 := q5 / 1000
|
||||
if q6 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q5], n)
|
||||
} else {
|
||||
n = writeFirstBuf(stream.buf, digits[q6], n)
|
||||
r6 := q5 - q6*1000
|
||||
writeBuf(stream.buf, digits[r6], n)
|
||||
n += 3
|
||||
}
|
||||
writeBuf(stream.buf, digits[r5], n)
|
||||
writeBuf(stream.buf, digits[r4], n+3)
|
||||
writeBuf(stream.buf, digits[r3], n+6)
|
||||
writeBuf(stream.buf, digits[r2], n+9)
|
||||
writeBuf(stream.buf, digits[r1], n+12)
|
||||
stream.n = n + 15
|
||||
}
|
||||
|
||||
// WriteInt64 write int64 to stream
|
||||
func (stream *Stream) WriteInt64(nval int64) {
|
||||
stream.ensure(20)
|
||||
n := stream.n
|
||||
var val uint64
|
||||
if nval < 0 {
|
||||
val = uint64(-nval)
|
||||
stream.buf[n] = '-'
|
||||
n++
|
||||
} else {
|
||||
val = uint64(nval)
|
||||
}
|
||||
q1 := val / 1000
|
||||
if q1 == 0 {
|
||||
stream.n = writeFirstBuf(stream.buf, digits[val], n)
|
||||
return
|
||||
}
|
||||
r1 := val - q1*1000
|
||||
q2 := q1 / 1000
|
||||
if q2 == 0 {
|
||||
n := writeFirstBuf(stream.buf, digits[q1], n)
|
||||
writeBuf(stream.buf, digits[r1], n)
|
||||
stream.n = n + 3
|
||||
return
|
||||
}
|
||||
r2 := q1 - q2*1000
|
||||
q3 := q2 / 1000
|
||||
if q3 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q2], n)
|
||||
writeBuf(stream.buf, digits[r2], n)
|
||||
writeBuf(stream.buf, digits[r1], n+3)
|
||||
stream.n = n + 6
|
||||
return
|
||||
}
|
||||
r3 := q2 - q3*1000
|
||||
q4 := q3 / 1000
|
||||
if q4 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q3], n)
|
||||
writeBuf(stream.buf, digits[r3], n)
|
||||
writeBuf(stream.buf, digits[r2], n+3)
|
||||
writeBuf(stream.buf, digits[r1], n+6)
|
||||
stream.n = n + 9
|
||||
return
|
||||
}
|
||||
r4 := q3 - q4*1000
|
||||
q5 := q4 / 1000
|
||||
if q5 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q4], n)
|
||||
writeBuf(stream.buf, digits[r4], n)
|
||||
writeBuf(stream.buf, digits[r3], n+3)
|
||||
writeBuf(stream.buf, digits[r2], n+6)
|
||||
writeBuf(stream.buf, digits[r1], n+9)
|
||||
stream.n = n + 12
|
||||
return
|
||||
}
|
||||
r5 := q4 - q5*1000
|
||||
q6 := q5 / 1000
|
||||
if q6 == 0 {
|
||||
n = writeFirstBuf(stream.buf, digits[q5], n)
|
||||
} else {
|
||||
stream.buf[n] = byte(q6 + '0')
|
||||
n++
|
||||
r6 := q5 - q6*1000
|
||||
writeBuf(stream.buf, digits[r6], n)
|
||||
n += 3
|
||||
}
|
||||
writeBuf(stream.buf, digits[r5], n)
|
||||
writeBuf(stream.buf, digits[r4], n+3)
|
||||
writeBuf(stream.buf, digits[r3], n+6)
|
||||
writeBuf(stream.buf, digits[r2], n+9)
|
||||
writeBuf(stream.buf, digits[r1], n+12)
|
||||
stream.n = n + 15
|
||||
}
|
||||
|
||||
// WriteInt write int to stream
|
||||
func (stream *Stream) WriteInt(val int) {
|
||||
stream.WriteInt64(int64(val))
|
||||
}
|
||||
|
||||
// WriteUint write uint to stream
|
||||
func (stream *Stream) WriteUint(val uint) {
|
||||
stream.WriteUint64(uint64(val))
|
||||
}
|
||||
@@ -77,6 +77,7 @@ type Iterator struct {
|
||||
captureStartedAt int
|
||||
captured []byte
|
||||
Error error
|
||||
Attachment interface{} // open for customized decoder
|
||||
}
|
||||
|
||||
// NewIterator creates an empty Iterator instance
|
||||
@@ -167,7 +168,7 @@ func (iter *Iterator) isObjectEnd() bool {
|
||||
if c == '}' {
|
||||
return true
|
||||
}
|
||||
iter.ReportError("isObjectEnd", "object ended prematurely")
|
||||
iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c}))
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -200,8 +201,22 @@ func (iter *Iterator) ReportError(operation string, msg string) {
|
||||
if peekStart < 0 {
|
||||
peekStart = 0
|
||||
}
|
||||
iter.Error = fmt.Errorf("%s: %s, parsing %v ...%s... at %s", operation, msg, iter.head,
|
||||
string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
|
||||
peekEnd := iter.head + 10
|
||||
if peekEnd > iter.tail {
|
||||
peekEnd = iter.tail
|
||||
}
|
||||
parsing := string(iter.buf[peekStart:peekEnd])
|
||||
contextStart := iter.head - 50
|
||||
if contextStart < 0 {
|
||||
contextStart = 0
|
||||
}
|
||||
contextEnd := iter.head + 50
|
||||
if contextEnd > iter.tail {
|
||||
contextEnd = iter.tail
|
||||
}
|
||||
context := string(iter.buf[contextStart:contextEnd])
|
||||
iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
|
||||
operation, msg, iter.head-peekStart, parsing, context)
|
||||
}
|
||||
|
||||
// CurrentBuffer gets current buffer as string for debugging purpose
|
||||
@@ -210,7 +225,7 @@ func (iter *Iterator) CurrentBuffer() string {
|
||||
if peekStart < 0 {
|
||||
peekStart = 0
|
||||
}
|
||||
return fmt.Sprintf("parsing %v ...|%s|... at %s", iter.head,
|
||||
return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head,
|
||||
string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func (iter *Iterator) ReadArray() (ret bool) {
|
||||
case ',':
|
||||
return true
|
||||
default:
|
||||
iter.ReportError("ReadArray", "expect [ or , or ] or n, but found: "+string([]byte{c}))
|
||||
iter.ReportError("ReadArray", "expect [ or , or ] or n, but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) {
|
||||
c = iter.nextToken()
|
||||
}
|
||||
if c != ']' {
|
||||
iter.ReportError("ReadArrayCB", "expect ] in the end")
|
||||
iter.ReportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -53,6 +53,6 @@ func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return true // null
|
||||
}
|
||||
iter.ReportError("ReadArrayCB", "expect [ or n, but found: "+string([]byte{c}))
|
||||
iter.ReportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
@@ -339,3 +340,8 @@ func validateFloat(str string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ReadNumber read json.Number
|
||||
func (iter *Iterator) ReadNumber() (ret json.Number) {
|
||||
return json.Number(iter.readNumberAsString())
|
||||
}
|
||||
@@ -22,11 +22,17 @@ func init() {
|
||||
|
||||
// ReadUint read uint
|
||||
func (iter *Iterator) ReadUint() uint {
|
||||
if strconv.IntSize == 32 {
|
||||
return uint(iter.ReadUint32())
|
||||
}
|
||||
return uint(iter.ReadUint64())
|
||||
}
|
||||
|
||||
// ReadInt read int
|
||||
func (iter *Iterator) ReadInt() int {
|
||||
if strconv.IntSize == 32 {
|
||||
return int(iter.ReadInt32())
|
||||
}
|
||||
return int(iter.ReadInt64())
|
||||
}
|
||||
|
||||
@@ -115,6 +121,7 @@ func (iter *Iterator) ReadUint32() (ret uint32) {
|
||||
func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
ind := intDigits[c]
|
||||
if ind == 0 {
|
||||
iter.assertInteger()
|
||||
return 0 // single zero
|
||||
}
|
||||
if ind == invalidCharForNumber {
|
||||
@@ -127,12 +134,14 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
ind2 := intDigits[iter.buf[i]]
|
||||
if ind2 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
i++
|
||||
ind3 := intDigits[iter.buf[i]]
|
||||
if ind3 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*10 + uint32(ind2)
|
||||
}
|
||||
//iter.head = i + 1
|
||||
@@ -141,30 +150,35 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
ind4 := intDigits[iter.buf[i]]
|
||||
if ind4 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*100 + uint32(ind2)*10 + uint32(ind3)
|
||||
}
|
||||
i++
|
||||
ind5 := intDigits[iter.buf[i]]
|
||||
if ind5 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4)
|
||||
}
|
||||
i++
|
||||
ind6 := intDigits[iter.buf[i]]
|
||||
if ind6 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5)
|
||||
}
|
||||
i++
|
||||
ind7 := intDigits[iter.buf[i]]
|
||||
if ind7 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6)
|
||||
}
|
||||
i++
|
||||
ind8 := intDigits[iter.buf[i]]
|
||||
if ind8 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7)
|
||||
}
|
||||
i++
|
||||
@@ -172,6 +186,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
value = value*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8)
|
||||
iter.head = i
|
||||
if ind9 == invalidCharForNumber {
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -180,6 +195,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
ind = intDigits[iter.buf[i]]
|
||||
if ind == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
if value > uint32SafeToMultiply10 {
|
||||
@@ -194,6 +210,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
value = (value << 3) + (value << 1) + uint32(ind)
|
||||
}
|
||||
if !iter.loadMore() {
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -226,6 +243,7 @@ func (iter *Iterator) ReadUint64() uint64 {
|
||||
func (iter *Iterator) readUint64(c byte) (ret uint64) {
|
||||
ind := intDigits[c]
|
||||
if ind == 0 {
|
||||
iter.assertInteger()
|
||||
return 0 // single zero
|
||||
}
|
||||
if ind == invalidCharForNumber {
|
||||
@@ -233,11 +251,73 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
|
||||
return
|
||||
}
|
||||
value := uint64(ind)
|
||||
if iter.tail-iter.head > 10 {
|
||||
i := iter.head
|
||||
ind2 := intDigits[iter.buf[i]]
|
||||
if ind2 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
i++
|
||||
ind3 := intDigits[iter.buf[i]]
|
||||
if ind3 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*10 + uint64(ind2)
|
||||
}
|
||||
//iter.head = i + 1
|
||||
//value = value * 100 + uint32(ind2) * 10 + uint32(ind3)
|
||||
i++
|
||||
ind4 := intDigits[iter.buf[i]]
|
||||
if ind4 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*100 + uint64(ind2)*10 + uint64(ind3)
|
||||
}
|
||||
i++
|
||||
ind5 := intDigits[iter.buf[i]]
|
||||
if ind5 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4)
|
||||
}
|
||||
i++
|
||||
ind6 := intDigits[iter.buf[i]]
|
||||
if ind6 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5)
|
||||
}
|
||||
i++
|
||||
ind7 := intDigits[iter.buf[i]]
|
||||
if ind7 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6)
|
||||
}
|
||||
i++
|
||||
ind8 := intDigits[iter.buf[i]]
|
||||
if ind8 == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7)
|
||||
}
|
||||
i++
|
||||
ind9 := intDigits[iter.buf[i]]
|
||||
value = value*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8)
|
||||
iter.head = i
|
||||
if ind9 == invalidCharForNumber {
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
}
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
ind = intDigits[iter.buf[i]]
|
||||
if ind == invalidCharForNumber {
|
||||
iter.head = i
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
if value > uint64SafeToMultiple10 {
|
||||
@@ -252,7 +332,14 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
|
||||
value = (value << 3) + (value << 1) + uint64(ind)
|
||||
}
|
||||
if !iter.loadMore() {
|
||||
iter.assertInteger()
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) assertInteger() {
|
||||
if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' {
|
||||
iter.ReportError("assertInteger", "can not decode float as int")
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package jsoniter
|
||||
import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ReadObject read one field from object.
|
||||
@@ -19,15 +18,25 @@ func (iter *Iterator) ReadObject() (ret string) {
|
||||
c = iter.nextToken()
|
||||
if c == '"' {
|
||||
iter.unreadByte()
|
||||
return string(iter.readObjectFieldAsBytes())
|
||||
field := iter.ReadString()
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
||||
}
|
||||
return field
|
||||
}
|
||||
if c == '}' {
|
||||
return "" // end of object
|
||||
}
|
||||
iter.ReportError("ReadObject", `expect " after {`)
|
||||
iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
|
||||
return
|
||||
case ',':
|
||||
return string(iter.readObjectFieldAsBytes())
|
||||
field := iter.ReadString()
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
||||
}
|
||||
return field
|
||||
case '}':
|
||||
return "" // end of object
|
||||
default:
|
||||
@@ -36,62 +45,93 @@ func (iter *Iterator) ReadObject() (ret string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readFieldHash() int32 {
|
||||
// CaseInsensitive
|
||||
func (iter *Iterator) readFieldHash() int64 {
|
||||
hash := int64(0x811c9dc5)
|
||||
c := iter.nextToken()
|
||||
if c == '"' {
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
// require ascii string and no escape
|
||||
b := iter.buf[i]
|
||||
if 'A' <= b && b <= 'Z' {
|
||||
b += 'a' - 'A'
|
||||
}
|
||||
if b == '"' {
|
||||
iter.head = i + 1
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
|
||||
if c != '"' {
|
||||
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
|
||||
return 0
|
||||
}
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
// require ascii string and no escape
|
||||
b := iter.buf[i]
|
||||
if b == '\\' {
|
||||
iter.head = i
|
||||
for _, b := range iter.readStringSlowPath() {
|
||||
if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
|
||||
b += 'a' - 'A'
|
||||
}
|
||||
return int32(hash)
|
||||
hash ^= int64(b)
|
||||
hash *= 0x1000193
|
||||
}
|
||||
hash ^= int64(b)
|
||||
hash *= 0x1000193
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
|
||||
return 0
|
||||
}
|
||||
return hash
|
||||
}
|
||||
if !iter.loadMore() {
|
||||
iter.ReportError("readFieldHash", `incomplete field name`)
|
||||
return 0
|
||||
if b == '"' {
|
||||
iter.head = i + 1
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
|
||||
return 0
|
||||
}
|
||||
return hash
|
||||
}
|
||||
if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
|
||||
b += 'a' - 'A'
|
||||
}
|
||||
hash ^= int64(b)
|
||||
hash *= 0x1000193
|
||||
}
|
||||
if !iter.loadMore() {
|
||||
iter.ReportError("readFieldHash", `incomplete field name`)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
|
||||
return 0
|
||||
}
|
||||
|
||||
func calcHash(str string) int32 {
|
||||
func calcHash(str string, caseSensitive bool) int64 {
|
||||
hash := int64(0x811c9dc5)
|
||||
for _, b := range str {
|
||||
hash ^= int64(unicode.ToLower(b))
|
||||
if caseSensitive {
|
||||
hash ^= int64(b)
|
||||
} else {
|
||||
hash ^= int64(unicode.ToLower(b))
|
||||
}
|
||||
hash *= 0x1000193
|
||||
}
|
||||
return int32(hash)
|
||||
return int64(hash)
|
||||
}
|
||||
|
||||
// ReadObjectCB read object with callback, the key is ascii only and field name not copied
|
||||
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
|
||||
c := iter.nextToken()
|
||||
var field string
|
||||
if c == '{' {
|
||||
c = iter.nextToken()
|
||||
if c == '"' {
|
||||
iter.unreadByte()
|
||||
field := iter.readObjectFieldAsBytes()
|
||||
if !callback(iter, *(*string)(unsafe.Pointer(&field))) {
|
||||
field = iter.ReadString()
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
||||
}
|
||||
if !callback(iter, field) {
|
||||
return false
|
||||
}
|
||||
c = iter.nextToken()
|
||||
for c == ',' {
|
||||
field = iter.readObjectFieldAsBytes()
|
||||
if !callback(iter, *(*string)(unsafe.Pointer(&field))) {
|
||||
field = iter.ReadString()
|
||||
c = iter.nextToken()
|
||||
if c != ':' {
|
||||
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
||||
}
|
||||
if !callback(iter, field) {
|
||||
return false
|
||||
}
|
||||
c = iter.nextToken()
|
||||
@@ -105,14 +145,14 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
|
||||
if c == '}' {
|
||||
return true
|
||||
}
|
||||
iter.ReportError("ReadObjectCB", `expect " after }`)
|
||||
iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
if c == 'n' {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return true // null
|
||||
}
|
||||
iter.ReportError("ReadObjectCB", `expect { or n`)
|
||||
iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -125,7 +165,7 @@ func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
|
||||
iter.unreadByte()
|
||||
field := iter.ReadString()
|
||||
if iter.nextToken() != ':' {
|
||||
iter.ReportError("ReadMapCB", "expect : after object field")
|
||||
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
if !callback(iter, field) {
|
||||
@@ -135,7 +175,7 @@ func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
|
||||
for c == ',' {
|
||||
field = iter.ReadString()
|
||||
if iter.nextToken() != ':' {
|
||||
iter.ReportError("ReadMapCB", "expect : after object field")
|
||||
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
if !callback(iter, field) {
|
||||
@@ -152,14 +192,14 @@ func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
|
||||
if c == '}' {
|
||||
return true
|
||||
}
|
||||
iter.ReportError("ReadMapCB", `expect " after }`)
|
||||
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
if c == 'n' {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return true // null
|
||||
}
|
||||
iter.ReportError("ReadMapCB", `expect { or n`)
|
||||
iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -176,7 +216,7 @@ func (iter *Iterator) readObjectStart() bool {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return false
|
||||
}
|
||||
iter.ReportError("readObjectStart", "expect { or n")
|
||||
iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -192,7 +232,7 @@ func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {
|
||||
}
|
||||
}
|
||||
if iter.buf[iter.head] != ':' {
|
||||
iter.ReportError("readObjectFieldAsBytes", "expect : after object field")
|
||||
iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))
|
||||
return
|
||||
}
|
||||
iter.head++
|
||||
@@ -25,7 +25,7 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
||||
iter.skipFourBytes('a', 'l', 's', 'e')
|
||||
return false
|
||||
}
|
||||
iter.ReportError("ReadBool", "expect t or f")
|
||||
iter.ReportError("ReadBool", "expect t or f, but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,7 +59,9 @@ func (iter *Iterator) stopCapture() []byte {
|
||||
iter.captureStartedAt = -1
|
||||
iter.captured = nil
|
||||
if len(captured) == 0 {
|
||||
return remaining
|
||||
copied := make([]byte, len(remaining))
|
||||
copy(copied, remaining)
|
||||
return copied
|
||||
}
|
||||
captured = append(captured, remaining...)
|
||||
return captured
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build jsoniter-sloppy
|
||||
//+build jsoniter_sloppy
|
||||
|
||||
package jsoniter
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build !jsoniter-sloppy
|
||||
//+build !jsoniter_sloppy
|
||||
|
||||
package jsoniter
|
||||
|
||||
@@ -64,7 +64,7 @@ func (iter *Iterator) trySkipString() bool {
|
||||
} else if c == '\\' {
|
||||
return false
|
||||
} else if c < ' ' {
|
||||
iter.ReportError("ReadString",
|
||||
iter.ReportError("trySkipString",
|
||||
fmt.Sprintf(`invalid control character found: %d`, c))
|
||||
return true // already failed
|
||||
}
|
||||
@@ -28,7 +28,7 @@ func (iter *Iterator) ReadString() (ret string) {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return ""
|
||||
}
|
||||
iter.ReportError("ReadString", `expects " or n`)
|
||||
iter.ReportError("ReadString", `expects " or n, but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (iter *Iterator) readStringSlowPath() (ret string) {
|
||||
str = append(str, c)
|
||||
}
|
||||
}
|
||||
iter.ReportError("ReadString", "unexpected end of input")
|
||||
iter.ReportError("readStringSlowPath", "unexpected end of input")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ func (iter *Iterator) readEscapedChar(c byte, str []byte) []byte {
|
||||
case 't':
|
||||
str = append(str, '\t')
|
||||
default:
|
||||
iter.ReportError("ReadString",
|
||||
iter.ReportError("readEscapedChar",
|
||||
`invalid escape char after \`)
|
||||
return nil
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (iter *Iterator) ReadStringAsSlice() (ret []byte) {
|
||||
}
|
||||
return copied
|
||||
}
|
||||
iter.ReportError("ReadString", `expects " or n`)
|
||||
iter.ReportError("ReadStringAsSlice", `expects " or n, but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ func (iter *Iterator) readU4() (ret rune) {
|
||||
} else if c >= 'A' && c <= 'F' {
|
||||
ret = ret*16 + rune(c-'A'+10)
|
||||
} else {
|
||||
iter.ReportError("readU4", "expects 0~9 or a~f")
|
||||
iter.ReportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -17,41 +17,26 @@ type StreamPool interface {
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
|
||||
select {
|
||||
case stream := <-cfg.streamPool:
|
||||
stream.Reset(writer)
|
||||
return stream
|
||||
default:
|
||||
return NewStream(cfg, writer, 512)
|
||||
}
|
||||
stream := cfg.streamPool.Get().(*Stream)
|
||||
stream.Reset(writer)
|
||||
return stream
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) ReturnStream(stream *Stream) {
|
||||
stream.out = nil
|
||||
stream.Error = nil
|
||||
select {
|
||||
case cfg.streamPool <- stream:
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
stream.Attachment = nil
|
||||
cfg.streamPool.Put(stream)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator {
|
||||
select {
|
||||
case iter := <-cfg.iteratorPool:
|
||||
iter.ResetBytes(data)
|
||||
return iter
|
||||
default:
|
||||
return ParseBytes(cfg, data)
|
||||
}
|
||||
iter := cfg.iteratorPool.Get().(*Iterator)
|
||||
iter.ResetBytes(data)
|
||||
return iter
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
|
||||
iter.Error = nil
|
||||
select {
|
||||
case cfg.iteratorPool <- iter:
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
iter.Attachment = nil
|
||||
cfg.iteratorPool.Put(iter)
|
||||
}
|
||||
330
vendor/github.com/json-iterator/go/reflect.go
generated
vendored
Normal file
330
vendor/github.com/json-iterator/go/reflect.go
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
// ValDecoder is an internal type registered to cache as needed.
|
||||
// Don't confuse jsoniter.ValDecoder with json.Decoder.
|
||||
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
|
||||
//
|
||||
// Reflection on type to create decoders, which is then cached
|
||||
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
|
||||
// 1. create instance of new value, for example *int will need a int to be allocated
|
||||
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
|
||||
// 3. assignment to map, both key and value will be reflect.Value
|
||||
// For a simple struct binding, it will be reflect.Value free and allocation free
|
||||
type ValDecoder interface {
|
||||
Decode(ptr unsafe.Pointer, iter *Iterator)
|
||||
}
|
||||
|
||||
// ValEncoder is an internal type registered to cache as needed.
|
||||
// Don't confuse jsoniter.ValEncoder with json.Encoder.
|
||||
// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link).
|
||||
type ValEncoder interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
Encode(ptr unsafe.Pointer, stream *Stream)
|
||||
}
|
||||
|
||||
type checkIsEmpty interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
}
|
||||
|
||||
type ctx struct {
|
||||
*frozenConfig
|
||||
prefix string
|
||||
encoders map[reflect2.Type]ValEncoder
|
||||
decoders map[reflect2.Type]ValDecoder
|
||||
}
|
||||
|
||||
func (b *ctx) caseSensitive() bool {
|
||||
if b.frozenConfig == nil {
|
||||
// default is case-insensitive
|
||||
return false
|
||||
}
|
||||
return b.frozenConfig.caseSensitive
|
||||
}
|
||||
|
||||
func (b *ctx) append(prefix string) *ctx {
|
||||
return &ctx{
|
||||
frozenConfig: b.frozenConfig,
|
||||
prefix: b.prefix + " " + prefix,
|
||||
encoders: b.encoders,
|
||||
decoders: b.decoders,
|
||||
}
|
||||
}
|
||||
|
||||
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
|
||||
func (iter *Iterator) ReadVal(obj interface{}) {
|
||||
cacheKey := reflect2.RTypeOf(obj)
|
||||
decoder := iter.cfg.getDecoderFromCache(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(obj)
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
iter.ReportError("ReadVal", "can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = iter.cfg.DecoderOf(typ)
|
||||
}
|
||||
ptr := reflect2.PtrOf(obj)
|
||||
if ptr == nil {
|
||||
iter.ReportError("ReadVal", "can not read into nil pointer")
|
||||
return
|
||||
}
|
||||
decoder.Decode(ptr, iter)
|
||||
}
|
||||
|
||||
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
|
||||
func (stream *Stream) WriteVal(val interface{}) {
|
||||
if nil == val {
|
||||
stream.WriteNil()
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := stream.cfg.getEncoderFromCache(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = stream.cfg.EncoderOf(typ)
|
||||
}
|
||||
encoder.Encode(reflect2.PtrOf(val), stream)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder {
|
||||
cacheKey := typ.RType()
|
||||
decoder := cfg.getDecoderFromCache(cacheKey)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
ctx := &ctx{
|
||||
frozenConfig: cfg,
|
||||
prefix: "",
|
||||
decoders: map[reflect2.Type]ValDecoder{},
|
||||
encoders: map[reflect2.Type]ValEncoder{},
|
||||
}
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
decoder = decoderOfType(ctx, ptrType.Elem())
|
||||
cfg.addDecoderToCache(cacheKey, decoder)
|
||||
return decoder
|
||||
}
|
||||
|
||||
func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||
decoder := getTypeDecoderFromExtension(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfType(ctx, typ)
|
||||
for _, extension := range extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
for _, extension := range ctx.extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
return decoder
|
||||
}
|
||||
|
||||
func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||
decoder := ctx.decoders[typ]
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
placeholder := &placeholderDecoder{}
|
||||
ctx.decoders[typ] = placeholder
|
||||
decoder = _createDecoderOfType(ctx, typ)
|
||||
placeholder.decoder = decoder
|
||||
return decoder
|
||||
}
|
||||
|
||||
func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||
decoder := createDecoderOfJsonRawMessage(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfJsonNumber(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfMarshaler(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfAny(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfNative(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
switch typ.Kind() {
|
||||
case reflect.Interface:
|
||||
ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType)
|
||||
if isIFace {
|
||||
return &ifaceDecoder{valType: ifaceType}
|
||||
}
|
||||
return &efaceDecoder{}
|
||||
case reflect.Struct:
|
||||
return decoderOfStruct(ctx, typ)
|
||||
case reflect.Array:
|
||||
return decoderOfArray(ctx, typ)
|
||||
case reflect.Slice:
|
||||
return decoderOfSlice(ctx, typ)
|
||||
case reflect.Map:
|
||||
return decoderOfMap(ctx, typ)
|
||||
case reflect.Ptr:
|
||||
return decoderOfOptional(ctx, typ)
|
||||
default:
|
||||
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder {
|
||||
cacheKey := typ.RType()
|
||||
encoder := cfg.getEncoderFromCache(cacheKey)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
ctx := &ctx{
|
||||
frozenConfig: cfg,
|
||||
prefix: "",
|
||||
decoders: map[reflect2.Type]ValDecoder{},
|
||||
encoders: map[reflect2.Type]ValEncoder{},
|
||||
}
|
||||
encoder = encoderOfType(ctx, typ)
|
||||
if typ.LikePtr() {
|
||||
encoder = &onePtrEncoder{encoder}
|
||||
}
|
||||
cfg.addEncoderToCache(cacheKey, encoder)
|
||||
return encoder
|
||||
}
|
||||
|
||||
type onePtrEncoder struct {
|
||||
encoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
|
||||
}
|
||||
|
||||
func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
|
||||
}
|
||||
|
||||
func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
|
||||
encoder := getTypeEncoderFromExtension(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfType(ctx, typ)
|
||||
for _, extension := range extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
for _, extension := range ctx.extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
|
||||
func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
|
||||
encoder := ctx.encoders[typ]
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
placeholder := &placeholderEncoder{}
|
||||
ctx.encoders[typ] = placeholder
|
||||
encoder = _createEncoderOfType(ctx, typ)
|
||||
placeholder.encoder = encoder
|
||||
return encoder
|
||||
}
|
||||
func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
|
||||
encoder := createEncoderOfJsonRawMessage(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfJsonNumber(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfMarshaler(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfAny(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfNative(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
case reflect.Interface:
|
||||
return &dynamicEncoder{typ}
|
||||
case reflect.Struct:
|
||||
return encoderOfStruct(ctx, typ)
|
||||
case reflect.Array:
|
||||
return encoderOfArray(ctx, typ)
|
||||
case reflect.Slice:
|
||||
return encoderOfSlice(ctx, typ)
|
||||
case reflect.Map:
|
||||
return encoderOfMap(ctx, typ)
|
||||
case reflect.Ptr:
|
||||
return encoderOfOptional(ctx, typ)
|
||||
default:
|
||||
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
|
||||
}
|
||||
}
|
||||
|
||||
type lazyErrorDecoder struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.WhatIsNext() != NilValue {
|
||||
if iter.Error == nil {
|
||||
iter.Error = decoder.err
|
||||
}
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
|
||||
type lazyErrorEncoder struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
if ptr == nil {
|
||||
stream.WriteNil()
|
||||
} else if stream.Error == nil {
|
||||
stream.Error = encoder.err
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type placeholderDecoder struct {
|
||||
decoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.decoder.Decode(ptr, iter)
|
||||
}
|
||||
|
||||
type placeholderEncoder struct {
|
||||
encoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
encoder.encoder.Encode(ptr, stream)
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.encoder.IsEmpty(ptr)
|
||||
}
|
||||
104
vendor/github.com/json-iterator/go/reflect_array.go
generated
vendored
Normal file
104
vendor/github.com/json-iterator/go/reflect_array.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/modern-go/reflect2"
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder {
|
||||
arrayType := typ.(*reflect2.UnsafeArrayType)
|
||||
decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
|
||||
return &arrayDecoder{arrayType, decoder}
|
||||
}
|
||||
|
||||
func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder {
|
||||
arrayType := typ.(*reflect2.UnsafeArrayType)
|
||||
if arrayType.Len() == 0 {
|
||||
return emptyArrayEncoder{}
|
||||
}
|
||||
encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
|
||||
return &arrayEncoder{arrayType, encoder}
|
||||
}
|
||||
|
||||
type emptyArrayEncoder struct{}
|
||||
|
||||
func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteEmptyArray()
|
||||
}
|
||||
|
||||
func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type arrayEncoder struct {
|
||||
arrayType *reflect2.UnsafeArrayType
|
||||
elemEncoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteArrayStart()
|
||||
elemPtr := unsafe.Pointer(ptr)
|
||||
encoder.elemEncoder.Encode(elemPtr, stream)
|
||||
for i := 1; i < encoder.arrayType.Len(); i++ {
|
||||
stream.WriteMore()
|
||||
elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i)
|
||||
encoder.elemEncoder.Encode(elemPtr, stream)
|
||||
}
|
||||
stream.WriteArrayEnd()
|
||||
if stream.Error != nil && stream.Error != io.EOF {
|
||||
stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type arrayDecoder struct {
|
||||
arrayType *reflect2.UnsafeArrayType
|
||||
elemDecoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.doDecode(ptr, iter)
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
c := iter.nextToken()
|
||||
arrayType := decoder.arrayType
|
||||
if c == 'n' {
|
||||
iter.skipThreeBytes('u', 'l', 'l')
|
||||
return
|
||||
}
|
||||
if c != '[' {
|
||||
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
c = iter.nextToken()
|
||||
if c == ']' {
|
||||
return
|
||||
}
|
||||
iter.unreadByte()
|
||||
elemPtr := arrayType.UnsafeGetIndex(ptr, 0)
|
||||
decoder.elemDecoder.Decode(elemPtr, iter)
|
||||
length := 1
|
||||
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
|
||||
if length >= arrayType.Len() {
|
||||
iter.Skip()
|
||||
continue
|
||||
}
|
||||
idx := length
|
||||
length += 1
|
||||
elemPtr = arrayType.UnsafeGetIndex(ptr, idx)
|
||||
decoder.elemDecoder.Decode(elemPtr, iter)
|
||||
}
|
||||
if c != ']' {
|
||||
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
}
|
||||
70
vendor/github.com/json-iterator/go/reflect_dynamic.go
generated
vendored
Normal file
70
vendor/github.com/json-iterator/go/reflect_dynamic.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"github.com/modern-go/reflect2"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type dynamicEncoder struct {
|
||||
valType reflect2.Type
|
||||
}
|
||||
|
||||
func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
obj := encoder.valType.UnsafeIndirect(ptr)
|
||||
stream.WriteVal(obj)
|
||||
}
|
||||
|
||||
func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.valType.UnsafeIndirect(ptr) == nil
|
||||
}
|
||||
|
||||
type efaceDecoder struct {
|
||||
}
|
||||
|
||||
func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
pObj := (*interface{})(ptr)
|
||||
obj := *pObj
|
||||
if obj == nil {
|
||||
*pObj = iter.Read()
|
||||
return
|
||||
}
|
||||
typ := reflect2.TypeOf(obj)
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
*pObj = iter.Read()
|
||||
return
|
||||
}
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
ptrElemType := ptrType.Elem()
|
||||
if iter.WhatIsNext() == NilValue {
|
||||
if ptrElemType.Kind() != reflect.Ptr {
|
||||
iter.skipFourBytes('n', 'u', 'l', 'l')
|
||||
*pObj = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
if reflect2.IsNil(obj) {
|
||||
obj := ptrElemType.New()
|
||||
iter.ReadVal(obj)
|
||||
*pObj = obj
|
||||
return
|
||||
}
|
||||
iter.ReadVal(obj)
|
||||
}
|
||||
|
||||
type ifaceDecoder struct {
|
||||
valType *reflect2.UnsafeIFaceType
|
||||
}
|
||||
|
||||
func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
if iter.ReadNil() {
|
||||
decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew())
|
||||
return
|
||||
}
|
||||
obj := decoder.valType.UnsafeIndirect(ptr)
|
||||
if reflect2.IsNil(obj) {
|
||||
iter.ReportError("decode non empty interface", "can not unmarshal into nil")
|
||||
return
|
||||
}
|
||||
iter.ReadVal(obj)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user