mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-01 19:58:15 +00:00
Compare commits
562 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
697147a2e6 | ||
|
|
6df40a2471 | ||
|
|
0dba63909f | ||
|
|
0e3fdd0eea | ||
|
|
45a2b07cbd | ||
|
|
d10c163142 | ||
|
|
35abb7f89b | ||
|
|
9954e09ab7 | ||
|
|
95a21327fc | ||
|
|
89b6183ee9 | ||
|
|
5a98d65e86 | ||
|
|
f73d205bc7 | ||
|
|
7c37abe92d | ||
|
|
4749e77b0e | ||
|
|
6ff1898413 | ||
|
|
c9a30c9ca2 | ||
|
|
8c02d17bea | ||
|
|
34305c4ce4 | ||
|
|
cd88e6b2aa | ||
|
|
3ec7a53c62 | ||
|
|
6d44cede70 | ||
|
|
cc08c0835b | ||
|
|
54f8b787cb | ||
|
|
17557f9131 | ||
|
|
d54af8cd43 | ||
|
|
173e10fdf1 | ||
|
|
8f56990f6c | ||
|
|
6400c9b054 | ||
|
|
7418d85872 | ||
|
|
c580fa284c | ||
|
|
f2a1272303 | ||
|
|
316d7c2089 | ||
|
|
47026ea6ba | ||
|
|
3f677f2414 | ||
|
|
a593a11e59 | ||
|
|
7cdfc8475e | ||
|
|
bab2b0db48 | ||
|
|
89418eb848 | ||
|
|
9cadf05d89 | ||
|
|
6da1cf79d9 | ||
|
|
bee1df96dc | ||
|
|
01189d7edd | ||
|
|
c4b2b0a25d | ||
|
|
a4b2884e4e | ||
|
|
04d80f255d | ||
|
|
55686100aa | ||
|
|
718351831d | ||
|
|
d1b34f0f28 | ||
|
|
21b7061963 | ||
|
|
35daaf83d3 | ||
|
|
3b458f7a17 | ||
|
|
a5d9d0f7d3 | ||
|
|
3cd9b6434a | ||
|
|
355dfd48d1 | ||
|
|
bcd58a159b | ||
|
|
a2c12900aa | ||
|
|
901b89e733 | ||
|
|
31f8799083 | ||
|
|
8023d99e21 | ||
|
|
b4154405d1 | ||
|
|
04c17c7a76 | ||
|
|
62ec7d52ce | ||
|
|
7de668053f | ||
|
|
3a70e0b308 | ||
|
|
9b13201356 | ||
|
|
5e3916050c | ||
|
|
c957550511 | ||
|
|
44bf719883 | ||
|
|
3e8f15df90 | ||
|
|
602721a735 | ||
|
|
13c05f4da3 | ||
|
|
ce3a1c43a2 | ||
|
|
aa75e5734b | ||
|
|
2790fee257 | ||
|
|
eddebec1b6 | ||
|
|
030fee36ab | ||
|
|
f9724d1bde | ||
|
|
b20801ca40 | ||
|
|
a8e800bd7c | ||
|
|
d7530ae961 | ||
|
|
99d11e279f | ||
|
|
4fd8eb214b | ||
|
|
65f8703572 | ||
|
|
75823cc275 | ||
|
|
58e279244c | ||
|
|
3c964e10ab | ||
|
|
c3c32ec942 | ||
|
|
075e8d676b | ||
|
|
bcf1bd5c9e | ||
|
|
136d75fa65 | ||
|
|
091fa1fd1b | ||
|
|
ff3781dc2d | ||
|
|
6beb9f49cb | ||
|
|
80988ea869 | ||
|
|
0f2ff7eaa9 | ||
|
|
dda095023d | ||
|
|
adbcbba5d1 | ||
|
|
cbbd6aca04 | ||
|
|
405c64e07d | ||
|
|
42c08cbca6 | ||
|
|
33d5dd9bdd | ||
|
|
105dd528e9 | ||
|
|
f0f0efe7b8 | ||
|
|
e837d5a296 | ||
|
|
9834ee9787 | ||
|
|
44b2ab087c | ||
|
|
46ae3f80a6 | ||
|
|
7b38aa71e6 | ||
|
|
661bedd837 | ||
|
|
8526e12d73 | ||
|
|
3c7b660d62 | ||
|
|
964365ba69 | ||
|
|
32254b7acd | ||
|
|
521e255ad9 | ||
|
|
1b85292fd3 | ||
|
|
480815447a | ||
|
|
8d5e424c65 | ||
|
|
b4774d2354 | ||
|
|
26f238c248 | ||
|
|
e93c8c46e6 | ||
|
|
e21516b9d7 | ||
|
|
fbc11e8aec | ||
|
|
e9d29c21a7 | ||
|
|
8bfafc76de | ||
|
|
df3e8bf4a7 | ||
|
|
5665cfe492 | ||
|
|
5797540ed0 | ||
|
|
7f1af7cb02 | ||
|
|
32f47ad247 | ||
|
|
842f672baf | ||
|
|
d4cae0a623 | ||
|
|
f1147f65bb | ||
|
|
69d3fec488 | ||
|
|
cfb4ecf6f0 | ||
|
|
a92039687a | ||
|
|
625338d095 | ||
|
|
3f8ce99c50 | ||
|
|
0798b7b698 | ||
|
|
cbdf82e2fb | ||
|
|
e365c502ff | ||
|
|
97f3aa9174 | ||
|
|
2f5bb2eec4 | ||
|
|
917687c7a6 | ||
|
|
f9277e691d | ||
|
|
2706381eef | ||
|
|
b5560fcd52 | ||
|
|
782b865c55 | ||
|
|
3bfc86eaff | ||
|
|
c0282873fb | ||
|
|
4b870aca98 | ||
|
|
d0e3870c0f | ||
|
|
fb25eb87f2 | ||
|
|
cb35d3a0e5 | ||
|
|
8e6cabb31b | ||
|
|
bd31dd2425 | ||
|
|
65b67d2132 | ||
|
|
1fbb711324 | ||
|
|
cd75a36587 | ||
|
|
ec6b0bf297 | ||
|
|
c11b5d7447 | ||
|
|
4525c91be3 | ||
|
|
b97b342f59 | ||
|
|
c1058a903b | ||
|
|
3030449348 | ||
|
|
a2485d4ecc | ||
|
|
a20e71ac96 | ||
|
|
acc9990abd | ||
|
|
2d5315ff0e | ||
|
|
7de1a5e347 | ||
|
|
a4e3ad808e | ||
|
|
c953fa572b | ||
|
|
0c86085a5b | ||
|
|
a1f7ecd148 | ||
|
|
a20c55bea5 | ||
|
|
d7c2b388ef | ||
|
|
9fa8245e81 | ||
|
|
a5ca8bee4d | ||
|
|
09dea79a22 | ||
|
|
b632061eff | ||
|
|
da88be05e1 | ||
|
|
d4fa984f1d | ||
|
|
a0c0131e36 | ||
|
|
de9aa0cdee | ||
|
|
a752d1b88c | ||
|
|
db972be264 | ||
|
|
e304f8c115 | ||
|
|
47c7aa0361 | ||
|
|
7a63792929 | ||
|
|
7d7d796cd0 | ||
|
|
550b386995 | ||
|
|
5479adc80f | ||
|
|
b7012484f3 | ||
|
|
92e9f33036 | ||
|
|
ff1a22a05f | ||
|
|
9fb195cce8 | ||
|
|
7836e65dd4 | ||
|
|
123c7a4890 | ||
|
|
e635141d5b | ||
|
|
0d2cebccfe | ||
|
|
a80db8538c | ||
|
|
a6be1d0d74 | ||
|
|
a7e20b1996 | ||
|
|
4eb3efc221 | ||
|
|
a807fa9567 | ||
|
|
b80ad7e439 | ||
|
|
16aef8ac0d | ||
|
|
b59a1ca2f8 | ||
|
|
4fdfe0d468 | ||
|
|
95004218f7 | ||
|
|
bc7ede8fb3 | ||
|
|
b652fcc3a7 | ||
|
|
c978b9ef1f | ||
|
|
3a88e1031b | ||
|
|
51dd733ba4 | ||
|
|
79f0df3dfc | ||
|
|
9d92fd92e1 | ||
|
|
93f74c0363 | ||
|
|
43dbac5d25 | ||
|
|
53ea1ab1bd | ||
|
|
b10b050ab9 | ||
|
|
563dcd6893 | ||
|
|
30ac512a54 | ||
|
|
b04736f9bd | ||
|
|
bc240b3004 | ||
|
|
0f7e7fd209 | ||
|
|
766ed04422 | ||
|
|
c5e2d37337 | ||
|
|
fe83b68ac6 | ||
|
|
718ddea558 | ||
|
|
8d86b5347f | ||
|
|
39bd667fd0 | ||
|
|
0bb3ce6935 | ||
|
|
b56d60f058 | ||
|
|
bff7ffbc51 | ||
|
|
107c08988a | ||
|
|
f9ebfcb9c4 | ||
|
|
b701c7d56e | ||
|
|
103f61b685 | ||
|
|
e47ca7ab40 | ||
|
|
d79f4e9717 | ||
|
|
5d67693e8f | ||
|
|
af74f87ccd | ||
|
|
b8ef8c1521 | ||
|
|
6cc30b3272 | ||
|
|
e5b6125fa2 | ||
|
|
ac14c8906f | ||
|
|
9936adf473 | ||
|
|
bf9eb67ab9 | ||
|
|
9e7e8cbe9f | ||
|
|
b72a75f87d | ||
|
|
6cfcd8628a | ||
|
|
ddb12c0192 | ||
|
|
2032b94f61 | ||
|
|
860dc803fe | ||
|
|
5b43e4bbb8 | ||
|
|
ecd76e898d | ||
|
|
f55d4388e0 | ||
|
|
e7340c390f | ||
|
|
90441c2078 | ||
|
|
cef8f928bb | ||
|
|
98b9b5a933 | ||
|
|
d07a3d2f4c | ||
|
|
640df2c1f5 | ||
|
|
60340ac529 | ||
|
|
2bd4a27550 | ||
|
|
23bb57401c | ||
|
|
dd6daa709b | ||
|
|
dd85c3b721 | ||
|
|
94cb1ff9ea | ||
|
|
3ff6cdf491 | ||
|
|
c329d6fa90 | ||
|
|
249f3b3714 | ||
|
|
2d67de3151 | ||
|
|
5cdbd02404 | ||
|
|
b2ce86ef8a | ||
|
|
8e7acae013 | ||
|
|
343bbe808e | ||
|
|
cb9ab2fe58 | ||
|
|
4cbff97c43 | ||
|
|
88abae649c | ||
|
|
a7461433c6 | ||
|
|
440a70f4a3 | ||
|
|
02e73e1ae9 | ||
|
|
f93d0f6ac1 | ||
|
|
fd51fadaac | ||
|
|
11198f10f5 | ||
|
|
3b23ff18ea | ||
|
|
4f066c39ce | ||
|
|
ca68d8b043 | ||
|
|
407fb5d537 | ||
|
|
73a648b685 | ||
|
|
eb2a81f73d | ||
|
|
3968d00568 | ||
|
|
4f10da8d99 | ||
|
|
9e82ee2527 | ||
|
|
e237f53bfc | ||
|
|
98be491e72 | ||
|
|
71628dad0d | ||
|
|
cb7b2bf87e | ||
|
|
bfa430309a | ||
|
|
1c7d91cc55 | ||
|
|
2e865f4d4e | ||
|
|
13c9c674fd | ||
|
|
034275c6e2 | ||
|
|
4e5152d886 | ||
|
|
dc61512f20 | ||
|
|
1d60824d56 | ||
|
|
f89badd30f | ||
|
|
1b9d1b0110 | ||
|
|
6e2d530d61 | ||
|
|
9bf9b18f0a | ||
|
|
537c6ec1e6 | ||
|
|
a1f14005ab | ||
|
|
0cdacdfb35 | ||
|
|
bb58442054 | ||
|
|
4567b13115 | ||
|
|
8f8fb2b367 | ||
|
|
69d761d15e | ||
|
|
4f32cbf268 | ||
|
|
0eaaf18192 | ||
|
|
957d167199 | ||
|
|
e9d9d64527 | ||
|
|
78c50e340b | ||
|
|
9d483a3f0b | ||
|
|
b650dfba49 | ||
|
|
6980818337 | ||
|
|
224f7527e3 | ||
|
|
a66a88034a | ||
|
|
e1defaae5e | ||
|
|
78fdce28c7 | ||
|
|
60e94cf083 | ||
|
|
cf47f27164 | ||
|
|
cc7f9b89f3 | ||
|
|
600f3fbcd4 | ||
|
|
76a024137f | ||
|
|
31e34faa15 | ||
|
|
4d98faa515 | ||
|
|
d8210d5a83 | ||
|
|
7d3930a2fd | ||
|
|
347dba8501 | ||
|
|
fcacb46d01 | ||
|
|
3f388ec747 | ||
|
|
38bf4cfc03 | ||
|
|
c2f40c37b2 | ||
|
|
63d51afd11 | ||
|
|
d44931656a | ||
|
|
bbfd12eb11 | ||
|
|
7c94ff6c30 | ||
|
|
4fa4d36706 | ||
|
|
46208b1e91 | ||
|
|
b99332efd7 | ||
|
|
dd288f71f3 | ||
|
|
155c55900f | ||
|
|
0eb7b3beb0 | ||
|
|
a821b15634 | ||
|
|
87704e987e | ||
|
|
cb99116aca | ||
|
|
9ad73bf5a7 | ||
|
|
dba962ebb8 | ||
|
|
60a0f35fbc | ||
|
|
58e8552da0 | ||
|
|
d56a4055da | ||
|
|
30c4948541 | ||
|
|
80d148b175 | ||
|
|
2aa0d9a54d | ||
|
|
79cd55bd3a | ||
|
|
b378b8eb69 | ||
|
|
9635d494b3 | ||
|
|
0143f4e364 | ||
|
|
e161ade68c | ||
|
|
f575b02fda | ||
|
|
5f32f94810 | ||
|
|
d6b1ce09cf | ||
|
|
f23009f04f | ||
|
|
30bae01ea3 | ||
|
|
9068b0ee63 | ||
|
|
f8a0d3889b | ||
|
|
688fc77460 | ||
|
|
dd8922878d | ||
|
|
ab54e61805 | ||
|
|
f445c1eb4a | ||
|
|
980a6d66d3 | ||
|
|
21591916af | ||
|
|
b6c3d7b899 | ||
|
|
db0fcdd906 | ||
|
|
91fe9ba93f | ||
|
|
4c3b6c247d | ||
|
|
160e8f2fdc | ||
|
|
705577de51 | ||
|
|
0fb1d44bc4 | ||
|
|
bd20a60d6a | ||
|
|
b78c4332be | ||
|
|
636b516492 | ||
|
|
560718e976 | ||
|
|
ff687ae9c1 | ||
|
|
ca417426c7 | ||
|
|
55b30827f2 | ||
|
|
efbb11e093 | ||
|
|
5c0f914f38 | ||
|
|
802639e40d | ||
|
|
ad8b1e5dbd | ||
|
|
76d31e1b5e | ||
|
|
20396a1760 | ||
|
|
a3d8391f7b | ||
|
|
241e87d143 | ||
|
|
35f0b41fed | ||
|
|
cb5422c398 | ||
|
|
4ed6fafdfa | ||
|
|
53ce80ce91 | ||
|
|
233976c821 | ||
|
|
99fe1dc80f | ||
|
|
a4f9d1bfcc | ||
|
|
a4c362a1ba | ||
|
|
7c3c027295 | ||
|
|
569492e890 | ||
|
|
d840856093 | ||
|
|
925c1d77fc | ||
|
|
c0698cc33f | ||
|
|
ea8a4296e7 | ||
|
|
f85af46262 | ||
|
|
7a43775661 | ||
|
|
062dcf7007 | ||
|
|
ebb410062b | ||
|
|
4b864fd172 | ||
|
|
7e711f80d7 | ||
|
|
bf871ffd7f | ||
|
|
a89be8739c | ||
|
|
0bffce5aef | ||
|
|
d48f08acfe | ||
|
|
43132560f9 | ||
|
|
c56fff88a2 | ||
|
|
49fed8c4f6 | ||
|
|
b1a925dfc2 | ||
|
|
33791dc7b0 | ||
|
|
873a60b0d8 | ||
|
|
4b10656f9b | ||
|
|
e317b148dc | ||
|
|
ed03faaf07 | ||
|
|
02a7807dd8 | ||
|
|
615885e889 | ||
|
|
528ccdd458 | ||
|
|
c23ba6756f | ||
|
|
10e1d1a69e | ||
|
|
660c491265 | ||
|
|
c504a45404 | ||
|
|
919c929d30 | ||
|
|
ba4a02b46a | ||
|
|
be3d0b9c64 | ||
|
|
872fad049e | ||
|
|
9e648c392b | ||
|
|
d4f65bb8a3 | ||
|
|
3c54fd964b | ||
|
|
e7578548a5 | ||
|
|
99acd0bcd7 | ||
|
|
d0321df8cf | ||
|
|
e1f48ad35a | ||
|
|
d8f49e18d7 | ||
|
|
1f5eae5d6a | ||
|
|
ea9d60bbdf | ||
|
|
c2c3a84aaf | ||
|
|
1f03becd24 | ||
|
|
c721009491 | ||
|
|
55289c55bf | ||
|
|
ed2415eb72 | ||
|
|
aaa89429d3 | ||
|
|
12e5cf0b29 | ||
|
|
75601b81cc | ||
|
|
e203882d54 | ||
|
|
b9f1103b8a | ||
|
|
fd40cc61a4 | ||
|
|
38a6623f34 | ||
|
|
27e4f43b77 | ||
|
|
42515cfd33 | ||
|
|
5d3648b88a | ||
|
|
fc3ce7d1ab | ||
|
|
4898809eca | ||
|
|
ca5aaf62d3 | ||
|
|
c80f8d18c1 | ||
|
|
0d1559bdd4 | ||
|
|
8b39a0ee53 | ||
|
|
f675f6433c | ||
|
|
118093b613 | ||
|
|
1bb2a3bd08 | ||
|
|
2361dfb66a | ||
|
|
7b50004ec9 | ||
|
|
6e185d06a7 | ||
|
|
c949229395 | ||
|
|
e1d5fda5d4 | ||
|
|
a2603ec27e | ||
|
|
5f1b1ad42c | ||
|
|
4235a25640 | ||
|
|
88cd182349 | ||
|
|
7c824ef690 | ||
|
|
6bfa107f4e | ||
|
|
0cd8daf14e | ||
|
|
79f2adc50a | ||
|
|
dcfe38c58f | ||
|
|
51d9641de6 | ||
|
|
af6c0e6839 | ||
|
|
7c3cb5caa1 | ||
|
|
8f1bebba05 | ||
|
|
cda1525f84 | ||
|
|
72b05bc865 | ||
|
|
b3e4d9169b | ||
|
|
e2eb6af3e3 | ||
|
|
b188fde27e | ||
|
|
ba5eb3b5cf | ||
|
|
8ea293b988 | ||
|
|
f19803d364 | ||
|
|
b2d69aacf4 | ||
|
|
3331805a1c | ||
|
|
ea06768ad1 | ||
|
|
741c63052d | ||
|
|
e9912e9298 | ||
|
|
7dbc8f564a | ||
|
|
a2fe49b498 | ||
|
|
7dd5cfb510 | ||
|
|
00b741e5fb | ||
|
|
bb321fbe19 | ||
|
|
7330436713 | ||
|
|
f9c64891dd | ||
|
|
b752e4a9bb | ||
|
|
3e3c770c4e | ||
|
|
5a3f18d17d | ||
|
|
10bdcefa4a | ||
|
|
9bab626cbf | ||
|
|
effb608027 | ||
|
|
a96f2bd6ca | ||
|
|
ab3b721a54 | ||
|
|
4cfe36ae8e | ||
|
|
c7a797b966 | ||
|
|
ecc07e7793 | ||
|
|
43944a0ab1 | ||
|
|
27ce09860a | ||
|
|
3a2f6d5300 | ||
|
|
06d3229dc3 | ||
|
|
348fcb5b88 | ||
|
|
b4ca4d3cde | ||
|
|
0848f58cdd | ||
|
|
8e42f44807 | ||
|
|
88912640d0 | ||
|
|
c43a0beff0 | ||
|
|
a9640bd9e1 | ||
|
|
f11ffedb2b | ||
|
|
5d42c8352e | ||
|
|
7c1203d44c | ||
|
|
a0a33d94a7 | ||
|
|
b10123ff63 | ||
|
|
3a2c535592 | ||
|
|
6621424308 | ||
|
|
d215852f52 | ||
|
|
12c4c2238c | ||
|
|
85faa46fb3 | ||
|
|
cc354ea368 | ||
|
|
bed19a5340 | ||
|
|
9bb88a026a | ||
|
|
34cb163e38 | ||
|
|
a66f9e769b | ||
|
|
86153fd740 | ||
|
|
7eb4c6098e | ||
|
|
af3c598189 | ||
|
|
eac0bc6490 |
41
.appveyor/check-generate-code.bat
Normal file
41
.appveyor/check-generate-code.bat
Normal file
@@ -0,0 +1,41 @@
|
||||
:: Copyright 2018 Google Inc. All rights reserved.
|
||||
::
|
||||
:: Licensed under the Apache License, Version 2.0 (the "License");
|
||||
:: you may not use this file except in compliance with the License.
|
||||
:: You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing, software
|
||||
:: distributed under the License is distributed on an "AS IS" BASIS,
|
||||
:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
:: See the License for the specific language governing permissions and
|
||||
:: limitations under the License.
|
||||
set buildtype=Release
|
||||
if "%1"=="-b" set buildtype=%2
|
||||
|
||||
cd tests
|
||||
call generate_code.bat -b %buildtype% || goto FAIL
|
||||
|
||||
:: TODO: Release and Debug builds produce differences here for some reason.
|
||||
git checkout HEAD -- monster_test.bfbs
|
||||
git checkout HEAD -- arrays_test.bfbs
|
||||
|
||||
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||
goto SUCCESS
|
||||
|
||||
:DIFFFOUND
|
||||
@echo "" >&2
|
||||
@echo "ERROR: ********************************************************" >&2
|
||||
@echo "ERROR: The following differences were found after running the" >&2
|
||||
@echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
|
||||
@echo "ERROR: it after making changes in a generator or schema?" >&2
|
||||
@echo "ERROR: ********************************************************" >&2
|
||||
@echo "" >&2
|
||||
@git -c core.autocrlf=true --no-pager diff --binary
|
||||
|
||||
:FAIL
|
||||
set EXITCODE=1
|
||||
:SUCCESS
|
||||
cd ..
|
||||
EXIT /B %EXITCODE%
|
||||
18
.bazelci/presubmit.yml
Normal file
18
.bazelci/presubmit.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
buildifier: latest
|
||||
platforms:
|
||||
ubuntu1604:
|
||||
build_targets:
|
||||
- "..."
|
||||
test_targets:
|
||||
- "..."
|
||||
ubuntu1804:
|
||||
build_targets:
|
||||
- "..."
|
||||
test_targets:
|
||||
- "..."
|
||||
macos:
|
||||
build_targets:
|
||||
- "..."
|
||||
test_targets:
|
||||
- "..."
|
||||
@@ -1,7 +1,7 @@
|
||||
root = true
|
||||
[*.{cpp,cc,h}]
|
||||
end_of_line = LF
|
||||
# Don't set line endings to avoid conflict with core.autocrlf flag.
|
||||
# Line endings on checkout/checkin are controlled by .gitattributes file.
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,6 +1,8 @@
|
||||
Thank you for submitting a PR!
|
||||
|
||||
Please make sure you include the names of the affected language(s) in your PR title.
|
||||
Please delete this standard text once you've created your own description.
|
||||
|
||||
Make sure you include the names of the affected language(s) in your PR title.
|
||||
This helps us get the correct maintainers to look at your issue.
|
||||
|
||||
If you make changes to any of the code generators, be sure to run
|
||||
@@ -11,6 +13,8 @@ If your PR includes C++ code, please adhere to the Google C++ Style Guide,
|
||||
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
|
||||
so only some C++11 support is available.
|
||||
|
||||
For any C++ changes, please make sure to run `sh src/clang-format-git.sh`
|
||||
|
||||
Include other details as appropriate.
|
||||
|
||||
Thanks!
|
||||
|
||||
18
.github/stale.yml
vendored
Normal file
18
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 365
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
activity for 1 year. It will be automatically closed if no further activity occurs.
|
||||
To keep it open, simply post a new comment. Maintainers will re-open on
|
||||
new activity. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
32
.gitignore
vendored
32
.gitignore
vendored
@@ -1,6 +1,12 @@
|
||||
*_wire.txt
|
||||
*_wire.bin
|
||||
.DS_Store
|
||||
**/.build
|
||||
**/Packages
|
||||
/*.xcodeproj
|
||||
**/xcuserdata/
|
||||
**/xcshareddata/
|
||||
**/.swiftpm/
|
||||
*.o
|
||||
*.o.d
|
||||
*.class
|
||||
@@ -12,8 +18,11 @@
|
||||
*.vcxproj.user
|
||||
*.sln
|
||||
*.suo
|
||||
*.opendb
|
||||
*.keystore
|
||||
**/.vs/**
|
||||
**/bin/**
|
||||
!tests/rust_usage_test/bin/**
|
||||
**/gen/**
|
||||
**/libs/**
|
||||
**/obj/**
|
||||
@@ -23,8 +32,13 @@
|
||||
**/install_manifest.txt
|
||||
**/CMakeCache.txt
|
||||
**/CMakeTestfile.cmake
|
||||
**/CPackConfig.cmake
|
||||
**/CPackSourceConfig.cmake
|
||||
**/compile_commands.json
|
||||
**/Debug/**
|
||||
**/Release/**
|
||||
**/RelWithDebInfo/**
|
||||
**/x64/ #build artifacts from VS
|
||||
build.xml
|
||||
local.properties
|
||||
project.properties
|
||||
@@ -41,15 +55,20 @@ flatsamplebinary
|
||||
flatsamplebinary.exe
|
||||
flatsampletext
|
||||
flatsampletext.exe
|
||||
flatsamplebfbs
|
||||
flatsamplebfbs.exe
|
||||
grpctest
|
||||
grpctest.exe
|
||||
snapshot.sh
|
||||
tags
|
||||
tests/dart_gen
|
||||
tests/go_gen
|
||||
tests/monsterdata_java_wire.mon
|
||||
tests/monsterdata_java_wire_sp.mon
|
||||
tests/monsterdata_go_wire.mon
|
||||
tests/monsterdata_javascript_wire.mon
|
||||
tests/monsterdata_lobster_wire.mon
|
||||
tests/monsterdata_rust_wire.mon
|
||||
tests/unicode_test.mon
|
||||
tests/ts/
|
||||
tests/php/
|
||||
@@ -93,3 +112,16 @@ js/flatbuffers.mjs
|
||||
.ninja_log
|
||||
build.ninja
|
||||
rules.ninja
|
||||
.vscode
|
||||
dart/.pub/
|
||||
dart/.packages
|
||||
dart/pubspec.lock
|
||||
dart/.dart_tool/
|
||||
dart/build/
|
||||
dart/doc/api/
|
||||
Cargo.lock
|
||||
.corpus**
|
||||
.seed**
|
||||
grpc/google/
|
||||
**/Package.resolved
|
||||
.clangd/**
|
||||
|
||||
164
.travis.yml
164
.travis.yml
@@ -2,6 +2,50 @@ env:
|
||||
global:
|
||||
# Set at the root level as this is ignored when set under matrix.env.
|
||||
- GCC_VERSION="4.9"
|
||||
# Fail on first error if UBSAN or ASAN enabled for a target
|
||||
- UBSAN_OPTIONS=halt_on_error=1
|
||||
- ASAN_OPTIONS=halt_on_error=1
|
||||
# Travis machines have 2 cores
|
||||
- JOBS=2
|
||||
- MAKEFLAGS="-j 2"
|
||||
|
||||
conan-linux: &conan-linux
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
install:
|
||||
- ./conan/travis/install.sh
|
||||
script:
|
||||
- ./conan/travis/build.sh
|
||||
if: tag IS present
|
||||
|
||||
conan-linux-master: &conan-linux-master
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
install:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/install.sh; fi'
|
||||
script:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/build.sh; fi'
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
conan-osx: &conan-osx
|
||||
os: osx
|
||||
language: generic
|
||||
install:
|
||||
- ./conan/travis/install.sh
|
||||
script:
|
||||
- ./conan/travis/build.sh
|
||||
if: tag IS present
|
||||
|
||||
matrix:
|
||||
include:
|
||||
#- language: python
|
||||
@@ -30,20 +74,26 @@ matrix:
|
||||
# branch: master
|
||||
- language: cpp
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- docker-ce
|
||||
script:
|
||||
- bash .travis/build-and-run-docker-test-containers.sh
|
||||
|
||||
- language: cpp
|
||||
os:
|
||||
- linux
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
#- clang
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug BIICODE=false
|
||||
- BUILD_TYPE=Release BIICODE=false CONAN=true
|
||||
# biicode .deb files no longer available.
|
||||
# - BUILD_TYPE=Release BIICODE=true
|
||||
# - BUILD_TYPE=Debug BIICODE=true
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
@@ -54,12 +104,83 @@ matrix:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
|
||||
script:
|
||||
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
||||
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
||||
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/testing -s build_type=$BUILD_TYPE; fi
|
||||
- bash .travis/check-sources.sh
|
||||
- bash grpc/build_grpc.sh
|
||||
- cmake .
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DFLATBUFFERS_BUILD_GRPCTEST=ON
|
||||
-DGRPC_INSTALL_PATH=$TRAVIS_BUILD_DIR/google/grpc/install
|
||||
-DPROTOBUF_DOWNLOAD_PATH=$TRAVIS_BUILD_DIR/google/grpc/third_party/protobuf
|
||||
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||
- cmake --build . --target all --clean-first -- -j${JOBS}
|
||||
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash .travis/check-generate-code.sh
|
||||
|
||||
- language: cpp
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release
|
||||
|
||||
script:
|
||||
- bash grpc/build_grpc.sh
|
||||
- cmake .
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
-DFLATBUFFERS_BUILD_GRPCTEST=ON
|
||||
-DGRPC_INSTALL_PATH=$TRAVIS_BUILD_DIR/google/grpc/install
|
||||
-DPROTOBUF_DOWNLOAD_PATH=$TRAVIS_BUILD_DIR/google/grpc/third_party/protobuf
|
||||
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||
- cmake --build . -- -j${JOBS}
|
||||
- DYLD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash .travis/check-generate-code.sh
|
||||
|
||||
- <<: *conan-linux-master
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=conanio/gcc5
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=conanio/gcc6
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=9 CONAN_DOCKER_IMAGE=conanio/gcc9
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=7.0 CONAN_DOCKER_IMAGE=conanio/clang7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/clang8
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode7.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode8.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=8.1
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode9
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.0
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode9.4
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode10.2
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||
|
||||
- language: android
|
||||
sudo: true
|
||||
dist: trusty
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
@@ -69,9 +190,24 @@ matrix:
|
||||
- extra-android-m2repository
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
before_install:
|
||||
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||
# Output something every 10 minutes or Travis kills the job
|
||||
- while sleep 540; do echo "=====[ $SECONDS seconds still running ]====="; done &
|
||||
# Install the r17c version of the NDK that still so that we can continue to test with gnustl
|
||||
# and stlport.
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk
|
||||
- NDK_ZIP=$ANDROID_NDK_HOME/ndk.zip
|
||||
- mkdir -p $ANDROID_NDK_HOME
|
||||
- curl -o $NDK_ZIP https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
|
||||
- unzip -q -d $ANDROID_NDK_HOME $NDK_ZIP
|
||||
- rm $NDK_ZIP
|
||||
- mv $ANDROID_NDK_HOME/android-ndk-*/* $ANDROID_NDK_HOME
|
||||
- rmdir $ANDROID_NDK_HOME/android-ndk-*
|
||||
- export CMAKE=$(which cmake)
|
||||
# libc required for prebuilt llvm toolchain the NDK r17c.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq libc6; fi
|
||||
# Setup environment for Linux build which is required to build the sample.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
@@ -81,3 +217,5 @@ matrix:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
script:
|
||||
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||
# Kill the sleep loop
|
||||
- kill %1
|
||||
|
||||
45
.travis/build-and-run-docker-test-containers.sh
Executable file
45
.travis/build-and-run-docker-test-containers.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2018 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
|
||||
docker build -t build_cpp_image -f tests/docker/Dockerfile.testing.cpp.debian_buster .
|
||||
# Run tests with sanitizers (--cap-add SYS_PTRACE), both GCC and Clang.
|
||||
cpp_test_args="--cap-add SYS_PTRACE build_cpp_image sh ./tests/docker/cpp_test.run.sh Debug"
|
||||
docker run --rm $cpp_test_args
|
||||
docker run --rm --env CC=/usr/bin/clang --env CXX=/usr/bin/clang++ $cpp_test_args
|
||||
# Build flatc on debian once to speed up the test loop below.
|
||||
docker run --name flatc_container build_cpp_image sh ./tests/docker/build_flatc.run.sh Debug
|
||||
# All dependent dockers refer to 'flatc_debian_stretch'.
|
||||
docker cp flatc_container:/flatbuffers/flatc flatc_debian_stretch
|
||||
|
||||
for f in $(ls tests/docker/languages | sort)
|
||||
do
|
||||
# docker pull sometimes fails for unknown reasons, probably travisci-related. this retries the pull we need a few times.
|
||||
REQUIRED_BASE_IMAGE=$(cat tests/docker/languages/${f} | head -n 1 | awk ' { print $2 } ')
|
||||
|
||||
set +e
|
||||
n=0
|
||||
until [ $n -ge 5 ]
|
||||
do
|
||||
docker pull $REQUIRED_BASE_IMAGE && break
|
||||
n=$[$n+1]
|
||||
sleep 1
|
||||
done
|
||||
set -e
|
||||
|
||||
docker build -t $(echo ${f} | cut -f 3- -d .) -f tests/docker/languages/${f} .
|
||||
echo "TEST OK: ${f}"
|
||||
done
|
||||
36
.travis/check-generate-code.sh
Executable file
36
.travis/check-generate-code.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2018 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
|
||||
cd tests
|
||||
./generate_code.sh
|
||||
cd ..
|
||||
|
||||
# TODO: Linux and macos builds produce differences here for some reason.
|
||||
git checkout HEAD -- tests/monster_test.bfbs
|
||||
git checkout HEAD -- tests/arrays_test.bfbs
|
||||
git checkout HEAD -- samples/monster.bfbs
|
||||
|
||||
if ! git diff --quiet; then
|
||||
echo >&2
|
||||
echo "ERROR: ********************************************************" >&2
|
||||
echo "ERROR: The following differences were found after running the" >&2
|
||||
echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
|
||||
echo "ERROR: it after making changes in a generator or schema?" >&2
|
||||
echo "ERROR: ********************************************************" >&2
|
||||
echo >&2
|
||||
git diff --binary --exit-code
|
||||
fi
|
||||
33
.travis/check-sources.sh
Normal file
33
.travis/check-sources.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2018 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
set -e
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
scan_dir="$1"
|
||||
else
|
||||
scan_dir="$( pwd )"
|
||||
fi
|
||||
|
||||
py_checker="$0.py"
|
||||
|
||||
echo "scan root directory = '$scan_dir'"
|
||||
python3 --version
|
||||
# Scan recursively and search all *.cpp and *.h files using regex patterns.
|
||||
# Assume that script running from a root of Flatbuffers working dir.
|
||||
python3 $py_checker "ascii" "$scan_dir/include" "\.h$"
|
||||
python3 $py_checker "ascii" "$scan_dir/src" "\.cpp$"
|
||||
python3 $py_checker "ascii" "$scan_dir/tests" "\.h$"
|
||||
python3 $py_checker "utf-8" "$scan_dir/tests" "\.cpp$"
|
||||
35
.travis/check-sources.sh.py
Normal file
35
.travis/check-sources.sh.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
def check_encoding(encoding, scan_dir, regex_pattern):
|
||||
fname = None
|
||||
try:
|
||||
assert encoding in ['ascii', 'utf-8'], "unexpected encoding"
|
||||
cmp = re.compile(regex_pattern)
|
||||
for root, dirs, files in os.walk(scan_dir):
|
||||
fname = root
|
||||
cmp_list = [f for f in files if cmp.search(f) is not None]
|
||||
for f in cmp_list:
|
||||
fname = os.path.join(root, f)
|
||||
with open(fname, mode='rb') as test_file:
|
||||
btext = test_file.read()
|
||||
# check encoding
|
||||
btext.decode(encoding=encoding, errors="strict")
|
||||
if encoding == "utf-8" and btext.startswith(b'\xEF\xBB\xBF'):
|
||||
raise ValueError("unexpected BOM in file")
|
||||
# check LF line endings
|
||||
LF = btext.count(b'\n')
|
||||
CR = btext.count(b'\r')
|
||||
if CR!=0:
|
||||
raise ValueError("invalid line endings: LF({})/CR({})".format(LF, CR))
|
||||
except Exception as err:
|
||||
print("ERROR with [{}]: {}".format(fname, err))
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
# python check-sources.sh.py 'ascii' '.' '.*\.(cpp|h)$'
|
||||
res = check_encoding(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||
sys.exit(0 if res == 0 else -1)
|
||||
129
BUILD
129
BUILD
@@ -1,36 +1,22 @@
|
||||
licenses(["notice"])
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
features = [
|
||||
"-layering_check",
|
||||
"-parse_headers",
|
||||
],
|
||||
)
|
||||
|
||||
exports_files([
|
||||
"LICENSE",
|
||||
])
|
||||
|
||||
FLATBUFFERS_COPTS = [
|
||||
"-Wno-implicit-fallthrough",
|
||||
"-linclude",
|
||||
]
|
||||
|
||||
# Public flatc library to compile flatbuffer files at runtime.
|
||||
cc_library(
|
||||
name = "flatbuffers",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [":public_headers"],
|
||||
copts = FLATBUFFERS_COPTS,
|
||||
includes = ["include/"],
|
||||
hdrs = ["//:public_headers"],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
deps = ["//src:flatbuffers"],
|
||||
)
|
||||
|
||||
# Public C++ headers for the Flatbuffers library.
|
||||
@@ -43,8 +29,10 @@ filegroup(
|
||||
"include/flatbuffers/flexbuffers.h",
|
||||
"include/flatbuffers/hash.h",
|
||||
"include/flatbuffers/idl.h",
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/reflection.h",
|
||||
"include/flatbuffers/reflection_generated.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
],
|
||||
@@ -53,93 +41,38 @@ filegroup(
|
||||
# Public flatc compiler library.
|
||||
cc_library(
|
||||
name = "flatc_library",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/flatc.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/flatbuffers/flatc.h",
|
||||
":public_headers",
|
||||
],
|
||||
copts = FLATBUFFERS_COPTS,
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
linkstatic = 1,
|
||||
deps = [
|
||||
"//src:flatc_library",
|
||||
],
|
||||
)
|
||||
|
||||
# Public flatc compiler.
|
||||
cc_binary(
|
||||
name = "flatc",
|
||||
srcs = [
|
||||
"grpc/src/compiler/config.h",
|
||||
"grpc/src/compiler/cpp_generator.cc",
|
||||
"grpc/src/compiler/cpp_generator.h",
|
||||
"grpc/src/compiler/go_generator.cc",
|
||||
"grpc/src/compiler/go_generator.h",
|
||||
"grpc/src/compiler/java_generator.cc",
|
||||
"grpc/src/compiler/java_generator.h",
|
||||
"grpc/src/compiler/schema_interface.h",
|
||||
"src/flatc_main.cpp",
|
||||
"src/idl_gen_cpp.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_go.cpp",
|
||||
"src/idl_gen_grpc.cpp",
|
||||
"src/idl_gen_js.cpp",
|
||||
"src/idl_gen_json_schema.cpp",
|
||||
"src/idl_gen_php.cpp",
|
||||
"src/idl_gen_python.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
],
|
||||
copts = FLATBUFFERS_COPTS,
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
],
|
||||
deps = [
|
||||
":flatc_library",
|
||||
"//src:flatc",
|
||||
],
|
||||
)
|
||||
|
||||
# Test binary.
|
||||
cc_test(
|
||||
name = "flatbuffers_test",
|
||||
testonly = 1,
|
||||
filegroup(
|
||||
name = "flatc_headers",
|
||||
srcs = [
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
"tests/monster_test_generated.h",
|
||||
"tests/namespace_test/namespace_test1_generated.h",
|
||||
"tests/namespace_test/namespace_test2_generated.h",
|
||||
"tests/test.cpp",
|
||||
"tests/union_vector/union_vector_generated.h",
|
||||
":public_headers",
|
||||
"include/flatbuffers/flatc.h",
|
||||
],
|
||||
copts = FLATBUFFERS_COPTS + [
|
||||
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||
],
|
||||
data = [
|
||||
":tests/include_test/include_test1.fbs",
|
||||
":tests/include_test/sub/include_test2.fbs",
|
||||
":tests/monster_test.bfbs",
|
||||
":tests/monster_test.fbs",
|
||||
":tests/monsterdata_test.golden",
|
||||
":tests/prototest/imported.proto",
|
||||
":tests/prototest/test.golden",
|
||||
":tests/prototest/test.proto",
|
||||
":tests/prototest/test_union.golden",
|
||||
":tests/union_vector/union_vector.fbs",
|
||||
],
|
||||
includes = ["include/"],
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
# Library used by flatbuffer_cc_library rules.
|
||||
cc_library(
|
||||
name = "runtime_cc",
|
||||
hdrs = [
|
||||
"include/flatbuffers/base.h",
|
||||
"include/flatbuffers/flatbuffers.h",
|
||||
"include/flatbuffers/flexbuffers.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
)
|
||||
|
||||
@@ -71,6 +71,8 @@ function(build_flatbuffers flatbuffers_schemas
|
||||
)
|
||||
endif()
|
||||
|
||||
set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
set(schema_glob "*.fbs")
|
||||
# Generate the include files parameters.
|
||||
set(include_params "")
|
||||
@@ -97,7 +99,8 @@ function(build_flatbuffers flatbuffers_schemas
|
||||
-o ${generated_includes_dir}
|
||||
${include_params}
|
||||
-c ${schema}
|
||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies})
|
||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies}
|
||||
WORKING_DIRECTORY "${working_dir}")
|
||||
list(APPEND all_generated_files ${generated_include})
|
||||
endif()
|
||||
|
||||
@@ -109,7 +112,8 @@ function(build_flatbuffers flatbuffers_schemas
|
||||
-o ${binary_schemas_dir}
|
||||
${include_params}
|
||||
${schema}
|
||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies})
|
||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies}
|
||||
WORKING_DIRECTORY "${working_dir}")
|
||||
list(APPEND all_generated_files ${binary_schema})
|
||||
endif()
|
||||
|
||||
|
||||
4
CMake/DESCRIPTION.txt
Normal file
4
CMake/DESCRIPTION.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
FlatBuffers is a cross platform serialization library architected for
|
||||
maximum memory efficiency. It allows you to directly access serialized
|
||||
data without parsing/unpacking it first, while still having great
|
||||
forwards/backwards compatibility.
|
||||
@@ -45,6 +45,7 @@ if(FLATBUFFERS_FOUND)
|
||||
add_custom_command(OUTPUT ${FLATC_OUTPUT}
|
||||
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE}
|
||||
ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
|
||||
DEPENDS ${FILE}
|
||||
COMMENT "Building C++ header for ${FILE}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endforeach()
|
||||
|
||||
@@ -37,5 +37,3 @@ if (UNIX)
|
||||
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
|
||||
endif(UNIX)
|
||||
|
||||
INCLUDE(CPack)
|
||||
|
||||
34
CMake/PackageRedhat.cmake
Normal file
34
CMake/PackageRedhat.cmake
Normal file
@@ -0,0 +1,34 @@
|
||||
if (UNIX)
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_SOURCE_TGZ "ON")
|
||||
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FlatBuffers serialization library and schema compiler.")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
|
||||
set(CPACK_RPM_PACKAGE_MAINTAINER "Marc Butler <mockbutler@gmail.com>")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
|
||||
set(CPACK_RPM_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_NAME "flatbuffers")
|
||||
|
||||
# Assume this is not a cross complation build.
|
||||
if(NOT CPACK_RPM_PACKAGE_ARCHITECTURE)
|
||||
set(CPACK_RPM_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif(NOT CPACK_RPM_PACKAGE_ARCHITECTURE)
|
||||
|
||||
set(CPACK_RPM_PACKAGE_VENDOR "Google, Inc.")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/CMake/DESCRIPTION.txt)
|
||||
|
||||
# This may reduce rpm compatiblity with very old systems.
|
||||
set(CPACK_RPM_COMPRESSION_TYPE lzma)
|
||||
|
||||
set(CPACK_RPM_PACKAGE_NAME "flatbuffers")
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_RPM_PACKAGE_NAME}_${CPACK_RPM_PACKAGE_VERSION}_${CPACK_RPM_PACKAGE_ARCHITECTURE}")
|
||||
endif(UNIX)
|
||||
@@ -1,7 +1,7 @@
|
||||
find_program(GIT git)
|
||||
execute_process(
|
||||
COMMAND ${GIT} describe
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
343
CMakeLists.txt
343
CMakeLists.txt
@@ -1,4 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
# generate compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
project(FlatBuffers)
|
||||
|
||||
@@ -10,11 +13,31 @@ option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library"
|
||||
ON)
|
||||
option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
|
||||
ON)
|
||||
option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag"
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
|
||||
option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
|
||||
option(FLATBUFFERS_BUILD_SHAREDLIB
|
||||
"Enable the build of the flatbuffers shared library"
|
||||
OFF)
|
||||
option(FLATBUFFERS_LIBCXX_WITH_CLANG "Force libc++ when using Clang" ON)
|
||||
# NOTE: Sanitizer check only works on Linux & OSX (gcc & llvm).
|
||||
option(FLATBUFFERS_CODE_SANITIZE
|
||||
"Add '-fsanitize' flags to 'flattests' and 'flatc' targets."
|
||||
OFF)
|
||||
option(FLATBUFFERS_PACKAGE_REDHAT
|
||||
"Build an rpm using the 'package' target."
|
||||
OFF)
|
||||
option(FLATBUFFERS_PACKAGE_DEBIAN
|
||||
"Build an deb using the 'package' target."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_CPP17
|
||||
"Enable the build of c++17 test target. \"
|
||||
Requirements: Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_LEGACY
|
||||
"Run C++ code generator with '--cpp-std c++0x' switch."
|
||||
OFF)
|
||||
|
||||
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
message(WARNING
|
||||
@@ -22,8 +45,29 @@ if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
set(FLATBUFFERS_BUILD_TESTS OFF)
|
||||
endif()
|
||||
|
||||
if(DEFINED FLATBUFFERS_MAX_PARSING_DEPTH)
|
||||
# Override the default recursion depth limit.
|
||||
add_definitions(-DFLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH})
|
||||
message(STATUS "FLATBUFFERS_MAX_PARSING_DEPTH: ${FLATBUFFERS_MAX_PARSING_DEPTH}")
|
||||
endif()
|
||||
|
||||
# Auto-detect locale-narrow 'strtod_l' and 'strtoull_l' functions.
|
||||
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 0)
|
||||
if(MSVC)
|
||||
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(_strtoui64_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
else()
|
||||
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(strtoull_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
endif()
|
||||
if(FLATBUFFERS_HAS_STRTOF_L AND FLATBUFFERS_HAS_STRTOULL_L)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 1)
|
||||
endif()
|
||||
endif()
|
||||
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/code_generators.h
|
||||
include/flatbuffers/base.h
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
@@ -35,7 +79,6 @@ set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/registry.h
|
||||
include/flatbuffers/minireflect.h
|
||||
src/code_generators.cpp
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
src/reflection.cpp
|
||||
@@ -45,16 +88,25 @@ set(FlatBuffers_Library_SRCS
|
||||
set(FlatBuffers_Compiler_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_cpp.cpp
|
||||
src/idl_gen_general.cpp
|
||||
src/idl_gen_csharp.cpp
|
||||
src/idl_gen_dart.cpp
|
||||
src/idl_gen_kotlin.cpp
|
||||
src/idl_gen_go.cpp
|
||||
src/idl_gen_js.cpp
|
||||
src/idl_gen_java.cpp
|
||||
src/idl_gen_js_ts.cpp
|
||||
src/idl_gen_php.cpp
|
||||
src/idl_gen_python.cpp
|
||||
src/idl_gen_lobster.cpp
|
||||
src/idl_gen_lua.cpp
|
||||
src/idl_gen_rust.cpp
|
||||
src/idl_gen_fbs.cpp
|
||||
src/idl_gen_grpc.cpp
|
||||
src/idl_gen_json_schema.cpp
|
||||
src/idl_gen_swift.cpp
|
||||
src/flatc.cpp
|
||||
src/flatc_main.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
grpc/src/compiler/cpp_generator.cc
|
||||
@@ -62,6 +114,11 @@ set(FlatBuffers_Compiler_SRCS
|
||||
grpc/src/compiler/go_generator.cc
|
||||
grpc/src/compiler/java_generator.h
|
||||
grpc/src/compiler/java_generator.cc
|
||||
grpc/src/compiler/python_generator.h
|
||||
grpc/src/compiler/python_private_generator.h
|
||||
grpc/src/compiler/python_generator.cc
|
||||
grpc/src/compiler/swift_generator.h
|
||||
grpc/src/compiler/swift_generator.cc
|
||||
)
|
||||
|
||||
set(FlatHash_SRCS
|
||||
@@ -73,8 +130,39 @@ set(FlatBuffers_Tests_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_fbs.cpp
|
||||
tests/test.cpp
|
||||
tests/test_assert.h
|
||||
tests/test_assert.cpp
|
||||
tests/test_builder.h
|
||||
tests/test_builder.cpp
|
||||
tests/native_type_test_impl.h
|
||||
tests/native_type_test_impl.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
# file generate by running compiler on namespace_test/namespace_test1.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test1_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test2_generated.h
|
||||
# file generate by running compiler on union_vector/union_vector.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/union_vector/union_vector_generated.h
|
||||
# file generate by running compiler on tests/arrays_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/arrays_test_generated.h
|
||||
# file generate by running compiler on tests/native_type_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/native_type_test_generated.h
|
||||
# file generate by running compiler on tests/monster_extra.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_extra_generated.h
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_bfbs_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Tests_CPP17_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
tests/test_assert.h
|
||||
tests/test_assert.cpp
|
||||
tests/cpp17/test_cpp17.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/cpp17/generated_cpp17/monster_test_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_Binary_SRCS
|
||||
@@ -91,14 +179,28 @@ set(FlatBuffers_Sample_Text_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_BFBS_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
samples/sample_bfbs.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_GRPCTest_SRCS
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/grpc.h
|
||||
include/flatbuffers/util.h
|
||||
src/util.cpp
|
||||
tests/monster_test.grpc.fb.h
|
||||
tests/test_assert.h
|
||||
tests/test_builder.h
|
||||
tests/monster_test.grpc.fb.cc
|
||||
tests/test_assert.cpp
|
||||
tests/test_builder.cpp
|
||||
grpc/tests/grpctest.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
grpc/tests/message_builder_test.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
# source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS})
|
||||
@@ -107,9 +209,11 @@ set(FlatBuffers_GRPCTest_SRCS
|
||||
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||
# do not apply any global settings if the toolchain
|
||||
# is being configured externally
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -120,10 +224,11 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -faligned-new")
|
||||
"${CMAKE_CXX_FLAGS} -faligned-new -Werror=implicit-fallthrough=2")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
|
||||
@@ -137,14 +242,20 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
|
||||
list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Werror=unused-private-field") # enable warning
|
||||
endif()
|
||||
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
|
||||
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
||||
if(FLATBUFFERS_LIBCXX_WITH_CLANG)
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
|
||||
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Certain platforms such as ARM do not use signed chars by default
|
||||
@@ -165,6 +276,32 @@ if(FLATBUFFERS_CODE_COVERAGE)
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
function(add_fsanitize_to_target _target _sanitizer)
|
||||
if(WIN32)
|
||||
target_compile_definitions(${_target} PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
|
||||
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to ${_target}")
|
||||
else()
|
||||
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
|
||||
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
|
||||
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
|
||||
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
|
||||
)
|
||||
set(_sanitizer_flags "=address,undefined")
|
||||
if(_sanitizer MATCHES "=.*")
|
||||
# override default by user-defined sanitizer list
|
||||
set(_sanitizer_flags ${_sanitizer})
|
||||
endif()
|
||||
target_compile_options(${_target} PRIVATE
|
||||
-g -fsigned-char -fno-omit-frame-pointer
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
target_link_libraries(${_target} PRIVATE
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(BIICODE)
|
||||
include(biicode/cmake/biicode.cmake)
|
||||
return()
|
||||
@@ -174,11 +311,19 @@ include_directories(include)
|
||||
include_directories(grpc)
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||
# Attach header directory for when build via add_subdirectory().
|
||||
target_include_directories(flatbuffers INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||
target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATC)
|
||||
add_executable(flatc ${FlatBuffers_Compiler_SRCS})
|
||||
target_compile_options(flatc PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||
if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
|
||||
add_fsanitize_to_target(flatc ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
|
||||
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
|
||||
endif()
|
||||
@@ -186,6 +331,9 @@ if(FLATBUFFERS_BUILD_FLATC)
|
||||
# Make flatc.exe not depend on runtime dlls for easy distribution.
|
||||
target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
|
||||
endif()
|
||||
if(FLATBUFFERS_STATIC_FLATC AND NOT MSVC)
|
||||
target_link_libraries(flatc PRIVATE -static)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATHASH)
|
||||
@@ -200,56 +348,170 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
# - minor updated when there are additions in API/ABI
|
||||
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.9.0")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.12.0")
|
||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||
endif()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
# Global list of generated files.
|
||||
# Use the global property to be independent of PARENT_SCOPE.
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
|
||||
function(get_generated_output generated_files)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
set(${generated_files} ${tmp} PARENT_SCOPE)
|
||||
endfunction(get_generated_output)
|
||||
|
||||
function(register_generated_output file_name)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
list(APPEND tmp ${file_name})
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS ${tmp})
|
||||
endfunction(register_generated_output)
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
--reflect-names
|
||||
${OPT}
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_HEADER}'")
|
||||
register_generated_output(${GEN_HEADER})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "--no-includes;--gen-compare")
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
message(STATUS "`${SRC_FBS}`: add generation of binary (.bfbs) schema")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
-b --schema --bfbs-comments --bfbs-builtins
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BINARY_SCHEMA}'")
|
||||
register_generated_output(${GEN_BINARY_SCHEMA})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ embedded binary schema code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_bfbs_generated.h" GEN_BFBS_HEADER ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BFBS_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
${OPT}
|
||||
--bfbs-comments --bfbs-builtins --bfbs-gen-embed
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BFBS_HEADER}'")
|
||||
register_generated_output(${GEN_BFBS_HEADER})
|
||||
endfunction()
|
||||
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# TODO Add (monster_test.fbs monsterdata_test.json)->monsterdata_test.mon
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test1.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test2.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/union_vector/union_vector.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
|
||||
compile_flatbuffers_schema_to_binary(tests/arrays_test.fbs)
|
||||
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
|
||||
if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
||||
add_dependencies(flattests generated_code)
|
||||
set_property(TARGET flattests
|
||||
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
|
||||
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
|
||||
compile_flatbuffers_schema_to_binary(samples/monster.fbs)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
|
||||
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
|
||||
add_dependencies(flatsamplebinary generated_code)
|
||||
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
|
||||
add_dependencies(flatsampletext generated_code)
|
||||
add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
|
||||
add_dependencies(flatsamplebfbs generated_code)
|
||||
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
# Don't generate header for flattests_cpp17 target.
|
||||
# This target uses "generated_cpp17/monster_test_generated.h"
|
||||
# produced by direct call of generate_code.bat(sh) script.
|
||||
add_executable(flattests_cpp17 ${FlatBuffers_Tests_CPP17_SRCS})
|
||||
add_dependencies(flattests_cpp17 generated_code)
|
||||
target_compile_features(flattests_cpp17 PRIVATE cxx_std_17)
|
||||
target_compile_definitions(flattests_cpp17 PRIVATE
|
||||
FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1
|
||||
)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
add_fsanitize_to_target(flattests_cpp17 ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif(FLATBUFFERS_BUILD_CPP17)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
|
||||
endif()
|
||||
if(NOT GRPC_INSTALL_PATH)
|
||||
message(SEND_ERROR "GRPC_INSTALL_PATH variable is not defined. See grpc/README.md")
|
||||
endif()
|
||||
if(NOT PROTOBUF_DOWNLOAD_PATH)
|
||||
message(SEND_ERROR "PROTOBUF_DOWNLOAD_PATH variable is not defined. See grpc/README.md")
|
||||
endif()
|
||||
INCLUDE_DIRECTORIES(${GRPC_INSTALL_PATH}/include)
|
||||
INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
|
||||
LINK_DIRECTORIES(${GRPC_INSTALL_PATH}/lib)
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
add_dependencies(grpctest generated_code)
|
||||
target_link_libraries(grpctest PRIVATE grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
|
||||
# GRPC test has problems with alignment and will fail under ASAN/UBSAN.
|
||||
# add_fsanitize_to_target(grpctest ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/Version.cmake)
|
||||
@@ -292,7 +554,6 @@ if(FLATBUFFERS_INSTALL)
|
||||
install(
|
||||
TARGETS flatc EXPORT FlatcTargets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
|
||||
install(
|
||||
@@ -300,7 +561,6 @@ if(FLATBUFFERS_INSTALL)
|
||||
FILE FlatcTargets.cmake
|
||||
NAMESPACE flatbuffers::
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -334,13 +594,34 @@ endif()
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_test(NAME flattests COMMAND flattests)
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
add_test(NAME flattests_cpp17 COMMAND flattests_cpp17)
|
||||
endif()
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
add_test(NAME grpctest COMMAND grpctest)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This target is sync-barrier.
|
||||
# Other generate-dependent targets can depend on 'generated_code' only.
|
||||
get_generated_output(fbs_generated)
|
||||
if(fbs_generated)
|
||||
# message(STATUS "Add generated_code target with files:${fbs_generated}")
|
||||
add_custom_target(generated_code
|
||||
DEPENDS ${fbs_generated}
|
||||
COMMENT "All generated files were updated.")
|
||||
endif()
|
||||
|
||||
include(CMake/BuildFlatBuffers.cmake)
|
||||
|
||||
if(FLATBUFFERS_PACKAGE_DEBIAN)
|
||||
include(CMake/PackageDebian.cmake)
|
||||
if(UNIX)
|
||||
# Use of CPack only supported on Linux systems.
|
||||
if(FLATBUFFERS_PACKAGE_DEBIAN)
|
||||
include(CMake/PackageDebian.cmake)
|
||||
endif()
|
||||
if (FLATBUFFERS_PACKAGE_REDHAT)
|
||||
include(CMake/PackageRedhat.cmake)
|
||||
endif()
|
||||
include(CPack)
|
||||
endif()
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Google Inc.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
16
WORKSPACE
16
WORKSPACE
@@ -1,2 +1,18 @@
|
||||
workspace(name = "com_github_google_flatbuffers")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
],
|
||||
sha256 = "e88471aea3a3a4f19ec1310a55ba94772d087e9ce46e41ae38ecebe17935de7b",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains()
|
||||
|
||||
@@ -66,7 +66,7 @@ android {
|
||||
ndkBuild {
|
||||
targets "FlatBufferTest"
|
||||
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ LOCAL_MODULE := flatbuffers_extra
|
||||
LOCAL_SRC_FILES := src/idl_parser.cpp \
|
||||
src/idl_gen_text.cpp \
|
||||
src/reflection.cpp \
|
||||
src/util.cpp \
|
||||
src/code_generators.cpp
|
||||
src/util.cpp
|
||||
LOCAL_STATIC_LIBRARIES := flatbuffers
|
||||
LOCAL_ARM_MODE := arm
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -47,8 +46,14 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := FlatBufferTest
|
||||
LOCAL_SRC_FILES := android/jni/main.cpp \
|
||||
tests/test.cpp \
|
||||
tests/test_assert.h \
|
||||
tests/test_builder.h \
|
||||
tests/test_assert.cpp \
|
||||
tests/test_builder.cpp \
|
||||
tests/native_type_test_impl.h \
|
||||
tests/native_type_test_impl.cpp \
|
||||
src/idl_gen_fbs.cpp \
|
||||
src/idl_gen_general.cpp
|
||||
src/code_generators.cpp
|
||||
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
void android_main(android_app *app) {
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
void android_main(android_app *) {
|
||||
main(0, NULL);
|
||||
}
|
||||
|
||||
56
appveyor.yml
56
appveyor.yml
@@ -2,18 +2,37 @@ branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
|
||||
global:
|
||||
# Workaround for https://github.com/conda/conda-build/issues/636
|
||||
PYTHONIOENCODING: UTF-8
|
||||
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
|
||||
CMAKE_OPTIONS: ""
|
||||
CPP_TEST_OPTIONS: ""
|
||||
|
||||
matrix:
|
||||
- CMAKE_VS_VERSION: "10 2010"
|
||||
- CMAKE_VS_VERSION: "14 2015"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "10 2010"
|
||||
CMAKE_OPTIONS: "-DFLATBUFFERS_BUILD_LEGACY=1"
|
||||
CPP_TEST_OPTIONS: "--std-cpp c++0x"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "12 2013"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "14 2015"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_VS_VERSION: "15 2017"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CMAKE_VS_VERSION: "16 2019"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
platform:
|
||||
- x86
|
||||
@@ -24,21 +43,34 @@ configuration:
|
||||
- Release
|
||||
|
||||
before_build:
|
||||
- cmake -G"Visual Studio %CMAKE_VS_VERSION%"
|
||||
- set MONSTER_EXTRA=%MONSTER_EXTRA%
|
||||
- cmake . -G"Visual Studio %CMAKE_VS_VERSION%" -DFLATBUFFERS_CODE_SANITIZE=1 %CMAKE_OPTIONS%
|
||||
# This cuts down on a lot of noise generated by xamarin warnings.
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
||||
build:
|
||||
project: ALL_BUILD.vcxproj
|
||||
verbosity: minimal
|
||||
|
||||
after_build:
|
||||
- python conan/appveyor/install.py
|
||||
- python conan/appveyor/build.py
|
||||
|
||||
install:
|
||||
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
- rustup-init.exe -y
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- rustc -V
|
||||
- cargo -V
|
||||
|
||||
test_script:
|
||||
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
|
||||
- "cd tests"
|
||||
- rem "Building all code"
|
||||
- generate_code.bat -b %CONFIGURATION%
|
||||
- generate_code.bat -b %CONFIGURATION% %CPP_TEST_OPTIONS%
|
||||
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "cd .."
|
||||
@@ -47,6 +79,8 @@ test_script:
|
||||
- rem "---------------- Java -----------------"
|
||||
- "java -version"
|
||||
- "JavaTest.bat"
|
||||
- rem "---------------- Rust ----------------"
|
||||
- "RustTest.bat"
|
||||
- rem "---------------- JS -----------------"
|
||||
- "node --version"
|
||||
- "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json"
|
||||
@@ -71,8 +105,16 @@ test_script:
|
||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||
# supports building one project??
|
||||
- "cd FlatBuffers.Test"
|
||||
- "copy ..\\monsterdata_test.mon Resources\\"
|
||||
- "copy ..\\monsterdata_test.json Resources\\"
|
||||
- "dotnet new sln"
|
||||
- "dotnet sln add FlatBuffers.Test.csproj"
|
||||
- "nuget restore"
|
||||
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
|
||||
- "tempcs\\FlatBuffers.Test.exe"
|
||||
# Run tests with UNSAFE_BYTEBUFFER
|
||||
- "msbuild.exe /property:Configuration=Release;UnsafeByteBuffer=true;OutputPath=tempcsUnsafe /verbosity:minimal FlatBuffers.Test.csproj"
|
||||
- "tempcsUnsafe\\FlatBuffers.Test.exe"
|
||||
# TODO: add more languages.
|
||||
- "cd ..\\.."
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Biicode configuration file
|
||||
[paths]
|
||||
include
|
||||
[mains]
|
||||
!android/*
|
||||
[tests]
|
||||
tests/*
|
||||
@@ -1,21 +0,0 @@
|
||||
Biicode C/C++ dependency manager
|
||||
=================================
|
||||
|
||||
[](https://www.biicode.com/fenix/flatbuffers)
|
||||
|
||||
New with biicode? Check the [Getting Started Guide](http://docs.biicode.com/c++/gettingstarted.html).
|
||||
|
||||
How to build it?
|
||||
------------------
|
||||
Building it is too easy:
|
||||
|
||||
$ git clone git@github.com:google/flatbuffers.git
|
||||
$ cd flatbuffers
|
||||
$ bii init -L && bii build
|
||||
$ ./bin/any_executable
|
||||
|
||||
Or run its tests:
|
||||
|
||||
$ bii test
|
||||
|
||||
You can check [the examples/flatbuffers block](https://www.biicode.com/examples/flatbuffers).
|
||||
@@ -1,18 +0,0 @@
|
||||
set(BII_TESTS_WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# Copying data files to project/bin folder
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/samples")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples/monster.fbs"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/samples/monsterdata.json"
|
||||
DESTINATION
|
||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples")
|
||||
endif()
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
||||
DESTINATION
|
||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
endif()
|
||||
|
||||
ADD_BIICODE_TARGETS()
|
||||
|
||||
string(REPLACE " " ";" REPLACED_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
target_compile_options(${BII_BLOCK_TARGET} INTERFACE ${REPLACED_FLAGS})
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install libglu1-mesa-dev xorg-dev
|
||||
wget http://www.biicode.com/downloads/latest/ubuntu64
|
||||
mv ubuntu64 bii-ubuntu64.deb
|
||||
(sudo dpkg -i bii-ubuntu64.deb) && sudo apt-get -f install
|
||||
rm bii-ubuntu64.deb
|
||||
wget https://s3.amazonaws.com/biibinaries/thirdparty/cmake-3.0.2-Linux-64.tar.gz
|
||||
tar -xzf cmake-3.0.2-Linux-64.tar.gz
|
||||
sudo cp -fR cmake-3.0.2-Linux-64/* /usr
|
||||
rm -rf cmake-3.0.2-Linux-64
|
||||
rm cmake-3.0.2-Linux-64.tar.gz
|
||||
|
||||
cmake --version
|
||||
bii init -l && bii configure -DCMAKE_BUILD_TYPE=$1 && bii test
|
||||
261
build_defs.bzl
Normal file
261
build_defs.bzl
Normal file
@@ -0,0 +1,261 @@
|
||||
# Description:
|
||||
# BUILD rules for generating flatbuffer files in various languages.
|
||||
|
||||
"""
|
||||
Rules for building C++ flatbuffers with Bazel.
|
||||
"""
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
flatc_path = "@com_github_google_flatbuffers//:flatc"
|
||||
|
||||
DEFAULT_INCLUDE_PATHS = [
|
||||
"./",
|
||||
"$(GENDIR)",
|
||||
"$(BINDIR)",
|
||||
]
|
||||
|
||||
DEFAULT_FLATC_ARGS = [
|
||||
"--gen-object-api",
|
||||
"--gen-compare",
|
||||
"--no-includes",
|
||||
"--gen-mutable",
|
||||
"--reflect-names",
|
||||
"--cpp-ptr-type flatbuffers::unique_ptr",
|
||||
]
|
||||
|
||||
def flatbuffer_library_public(
|
||||
name,
|
||||
srcs,
|
||||
outs,
|
||||
language_flag,
|
||||
out_prefix = "",
|
||||
includes = [],
|
||||
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||
flatc_args = DEFAULT_FLATC_ARGS,
|
||||
reflection_name = "",
|
||||
reflection_visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
output_to_bindir = False):
|
||||
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
|
||||
|
||||
Args:
|
||||
name: Rule name.
|
||||
srcs: Source .fbs files. Sent in order to the compiler.
|
||||
outs: Output files from flatc.
|
||||
language_flag: Target language flag. One of [-c, -j, -js].
|
||||
out_prefix: Prepend this path to the front of all generated files except on
|
||||
single source targets. Usually is a directory name.
|
||||
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
||||
include_paths: Optional, list of paths the includes files can be found in.
|
||||
flatc_args: Optional, list of additional arguments to pass to flatc.
|
||||
reflection_name: Optional, if set this will generate the flatbuffer
|
||||
reflection binaries for the schemas.
|
||||
reflection_visibility: The visibility of the generated reflection Fileset.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
compatible_with: Optional, The list of environments this rule can be
|
||||
built for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
|
||||
|
||||
This rule creates a filegroup(name) with all generated source files, and
|
||||
optionally a Fileset([reflection_name]) with all generated reflection
|
||||
binaries.
|
||||
"""
|
||||
include_paths_cmd = ["-I %s" % (s) for s in include_paths]
|
||||
|
||||
# '$(@D)' when given a single source target will give the appropriate
|
||||
# directory. Appending 'out_prefix' is only necessary when given a build
|
||||
# target with multiple sources.
|
||||
output_directory = (
|
||||
("-o $(@D)/%s" % (out_prefix)) if len(srcs) > 1 else ("-o $(@D)")
|
||||
)
|
||||
genrule_cmd = " ".join([
|
||||
"SRCS=($(SRCS));",
|
||||
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
|
||||
"$(location %s)" % (flatc_path),
|
||||
" ".join(include_paths_cmd),
|
||||
" ".join(flatc_args),
|
||||
language_flag,
|
||||
output_directory,
|
||||
"$$f;",
|
||||
"done",
|
||||
])
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = srcs + includes,
|
||||
outs = outs,
|
||||
output_to_bindir = output_to_bindir,
|
||||
tools = [flatc_path],
|
||||
cmd = genrule_cmd,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
message = "Generating flatbuffer files for %s:" % (name),
|
||||
)
|
||||
if reflection_name:
|
||||
reflection_genrule_cmd = " ".join([
|
||||
"SRCS=($(SRCS));",
|
||||
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
|
||||
"$(location %s)" % (flatc_path),
|
||||
"-b --schema",
|
||||
" ".join(flatc_args),
|
||||
" ".join(include_paths_cmd),
|
||||
language_flag,
|
||||
output_directory,
|
||||
"$$f;",
|
||||
"done",
|
||||
])
|
||||
reflection_outs = [
|
||||
(out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
|
||||
for s in srcs
|
||||
]
|
||||
native.genrule(
|
||||
name = "%s_srcs" % reflection_name,
|
||||
srcs = srcs + includes,
|
||||
outs = reflection_outs,
|
||||
output_to_bindir = output_to_bindir,
|
||||
tools = [flatc_path],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
cmd = reflection_genrule_cmd,
|
||||
message = "Generating flatbuffer reflection binary for %s:" % (name),
|
||||
)
|
||||
native.filegroup(
|
||||
name = "%s_out" % reflection_name,
|
||||
srcs = reflection_outs,
|
||||
visibility = reflection_visibility,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
)
|
||||
|
||||
def flatbuffer_cc_library(
|
||||
name,
|
||||
srcs,
|
||||
srcs_filegroup_name = "",
|
||||
out_prefix = "",
|
||||
includes = [],
|
||||
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||
flatc_args = DEFAULT_FLATC_ARGS,
|
||||
visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
srcs_filegroup_visibility = None,
|
||||
gen_reflections = False):
|
||||
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
|
||||
|
||||
Args:
|
||||
name: Rule name.
|
||||
srcs: Source .fbs files. Sent in order to the compiler.
|
||||
srcs_filegroup_name: Name of the output filegroup that holds srcs. Pass this
|
||||
filegroup into the `includes` parameter of any other
|
||||
flatbuffer_cc_library that depends on this one's schemas.
|
||||
out_prefix: Prepend this path to the front of all generated files. Usually
|
||||
is a directory name.
|
||||
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
||||
** SEE REMARKS BELOW **
|
||||
include_paths: Optional, list of paths the includes files can be found in.
|
||||
flatc_args: Optional list of additional arguments to pass to flatc
|
||||
(e.g. --gen-mutable).
|
||||
visibility: The visibility of the generated cc_library. By default, use the
|
||||
default visibility of the project.
|
||||
srcs_filegroup_visibility: The visibility of the generated srcs filegroup.
|
||||
By default, use the value of the visibility parameter above.
|
||||
gen_reflections: Optional, if true this will generate the flatbuffer
|
||||
reflection binaries for the schemas.
|
||||
compatible_with: Optional, The list of environments this rule can be built
|
||||
for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
|
||||
This produces:
|
||||
filegroup([name]_srcs): all generated .h files.
|
||||
filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
|
||||
Other flatbuffer_cc_library's can pass this in for their `includes`
|
||||
parameter, if they depend on the schemas in this library.
|
||||
Fileset([name]_reflection): (Optional) all generated reflection binaries.
|
||||
cc_library([name]): library with sources and flatbuffers deps.
|
||||
|
||||
Remarks:
|
||||
** Because the genrule used to call flatc does not have any trivial way of
|
||||
computing the output list of files transitively generated by includes and
|
||||
--gen-includes (the default) being defined for flatc, the --gen-includes
|
||||
flag will not work as expected. The way around this is to add a dependency
|
||||
to the flatbuffer_cc_library defined alongside the flatc included Fileset.
|
||||
For example you might define:
|
||||
|
||||
flatbuffer_cc_library(
|
||||
name = "my_fbs",
|
||||
srcs = [ "schemas/foo.fbs" ],
|
||||
includes = [ "//third_party/bazz:bazz_fbs_includes" ],
|
||||
)
|
||||
|
||||
In which foo.fbs includes a few files from the Fileset defined at
|
||||
//third_party/bazz:bazz_fbs_includes. When compiling the library that
|
||||
includes foo_generated.h, and therefore has my_fbs as a dependency, it
|
||||
will fail to find any of the bazz *_generated.h files unless you also
|
||||
add bazz's flatbuffer_cc_library to your own dependency list, e.g.:
|
||||
|
||||
cc_library(
|
||||
name = "my_lib",
|
||||
deps = [
|
||||
":my_fbs",
|
||||
"//third_party/bazz:bazz_fbs"
|
||||
],
|
||||
)
|
||||
|
||||
Happy dependent Flatbuffering!
|
||||
'''
|
||||
output_headers = [
|
||||
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
|
||||
for s in srcs
|
||||
]
|
||||
reflection_name = "%s_reflection" % name if gen_reflections else ""
|
||||
|
||||
srcs_lib = "%s_srcs" % (name)
|
||||
flatbuffer_library_public(
|
||||
name = srcs_lib,
|
||||
srcs = srcs,
|
||||
outs = output_headers,
|
||||
language_flag = "-c",
|
||||
out_prefix = out_prefix,
|
||||
includes = includes,
|
||||
include_paths = include_paths,
|
||||
flatc_args = flatc_args,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
reflection_name = reflection_name,
|
||||
reflection_visibility = visibility,
|
||||
)
|
||||
cc_library(
|
||||
name = name,
|
||||
hdrs = [
|
||||
":" + srcs_lib,
|
||||
],
|
||||
srcs = [
|
||||
":" + srcs_lib,
|
||||
],
|
||||
features = [
|
||||
"-parse_headers",
|
||||
],
|
||||
deps = [
|
||||
"@com_github_google_flatbuffers//:runtime_cc",
|
||||
],
|
||||
includes = [],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
linkstatic = 1,
|
||||
visibility = visibility,
|
||||
)
|
||||
|
||||
# A filegroup for the `srcs`. That is, all the schema files for this
|
||||
# Flatbuffer set.
|
||||
native.filegroup(
|
||||
name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
|
||||
srcs = srcs,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
|
||||
)
|
||||
12
conan/CMakeLists.txt
Normal file
12
conan/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
message(STATUS "Conan FlatBuffers Wrapper")
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
if (WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
endif(WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt)
|
||||
8
conan/appveyor/build.py
Normal file
8
conan/appveyor/build.py
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
if os.getenv("APPVEYOR_REPO_TAG") != "true":
|
||||
print("Skip build step. It's not TAG")
|
||||
else:
|
||||
os.system("python conan/build.py")
|
||||
8
conan/appveyor/install.py
Normal file
8
conan/appveyor/install.py
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
if os.getenv("APPVEYOR_REPO_TAG") != "true":
|
||||
print("Skip step. It's not TAG")
|
||||
else:
|
||||
os.system("pip install conan conan-package-tools")
|
||||
69
conan/build.py
Normal file
69
conan/build.py
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from cpt.packager import ConanMultiPackager
|
||||
|
||||
|
||||
def set_appveyor_environment():
|
||||
if os.getenv("APPVEYOR") is not None:
|
||||
compiler_version = os.getenv("CMAKE_VS_VERSION").split(" ")[0].replace('"', '')
|
||||
os.environ["CONAN_VISUAL_VERSIONS"] = compiler_version
|
||||
os.environ["CONAN_STABLE_BRANCH_PATTERN"] = "master"
|
||||
ci_platform = os.getenv("Platform").replace('"', '')
|
||||
ci_platform = "x86" if ci_platform == "x86" else "x86_64"
|
||||
os.environ["CONAN_ARCHS"] = ci_platform
|
||||
os.environ["CONAN_BUILD_TYPES"] = os.getenv("Configuration").replace('"', '')
|
||||
|
||||
|
||||
def get_branch():
|
||||
try:
|
||||
for line in subprocess.check_output("git branch", shell=True).decode().splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith("*") and " (HEAD detached" not in line:
|
||||
return line.replace("*", "", 1).strip()
|
||||
return ""
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
def get_version():
|
||||
version = get_branch()
|
||||
if os.getenv("TRAVIS", False):
|
||||
version = os.getenv("TRAVIS_BRANCH")
|
||||
|
||||
if os.getenv("APPVEYOR", False):
|
||||
version = os.getenv("APPVEYOR_REPO_BRANCH")
|
||||
if os.getenv("APPVEYOR_REPO_TAG") == "true":
|
||||
version = os.getenv("APPVEYOR_REPO_TAG_NAME")
|
||||
|
||||
match = re.search(r"v(\d+\.\d+\.\d+.*)", version)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return version
|
||||
|
||||
|
||||
def get_reference(username):
|
||||
return "flatbuffers/{}@google/stable".format(get_version())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel")
|
||||
username = os.getenv("CONAN_USERNAME", "google")
|
||||
upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers")
|
||||
stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*")
|
||||
test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package"))
|
||||
upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
|
||||
set_appveyor_environment()
|
||||
|
||||
builder = ConanMultiPackager(reference=get_reference(username),
|
||||
username=username,
|
||||
login_username=login_username,
|
||||
upload=upload,
|
||||
stable_branch_pattern=stable_branch_pattern,
|
||||
upload_only_when_stable=upload_only_when_stable,
|
||||
test_folder=test_folder)
|
||||
builder.add_common_builds(pure_c=False)
|
||||
builder.run()
|
||||
9
conan/test_package/CMakeLists.txt
Normal file
9
conan/test_package/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
project(test_package CXX)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
add_executable(${PROJECT_NAME} test_package.cpp)
|
||||
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
|
||||
21
conan/test_package/conanfile.py
Normal file
21
conan/test_package/conanfile.py
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from conans import ConanFile, CMake
|
||||
import os
|
||||
|
||||
|
||||
class TestPackageConan(ConanFile):
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def test(self):
|
||||
bin_path = os.path.join("bin", "test_package")
|
||||
self.run(bin_path, run_environment=True)
|
||||
self.run("flatc --version", run_environment=True)
|
||||
self.run("flathash fnv1_16 conan", run_environment=True)
|
||||
35
conan/test_package/test_package.cpp
Normal file
35
conan/test_package/test_package.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
// Test to validate Conan package generated
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
|
||||
const std::string filename("conanbuildinfo.cmake");
|
||||
|
||||
if (flatbuffers::FileExists(filename.c_str())) {
|
||||
std::cout << "File " << filename << " exists.\n";
|
||||
} else {
|
||||
std::cout << "File " << filename << " does not exist.\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
14
conan/travis/build.sh
Executable file
14
conan/travis/build.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||
if which pyenv > /dev/null; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
pyenv activate conan
|
||||
fi
|
||||
|
||||
conan user
|
||||
python conan/build.py
|
||||
22
conan/travis/install.sh
Executable file
22
conan/travis/install.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||
brew update || brew update
|
||||
brew outdated pyenv || brew upgrade pyenv
|
||||
brew install pyenv-virtualenv
|
||||
brew install cmake || true
|
||||
|
||||
if which pyenv > /dev/null; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
|
||||
pyenv install 2.7.10
|
||||
pyenv virtualenv 2.7.10 conan
|
||||
pyenv rehash
|
||||
pyenv activate conan
|
||||
fi
|
||||
|
||||
pip install -U conan_package_tools conan
|
||||
62
conanfile.py
62
conanfile.py
@@ -4,50 +4,72 @@
|
||||
"""Conan recipe package for Google FlatBuffers
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
from conans import ConanFile, CMake, tools
|
||||
|
||||
|
||||
class FlatbuffersConan(ConanFile):
|
||||
name = "flatbuffers"
|
||||
version = "1.9.0"
|
||||
license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
|
||||
license = "Apache-2.0"
|
||||
url = "https://github.com/google/flatbuffers"
|
||||
homepage = "http://google.github.io/flatbuffers/"
|
||||
author = "Wouter van Oortmerssen"
|
||||
topics = ("conan", "flatbuffers", "serialization", "rpc", "json-parser")
|
||||
description = "Memory Efficient Serialization Library"
|
||||
settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
|
||||
options = {"shared": [True, False]}
|
||||
default_options = "shared=False"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||
default_options = {"shared": False, "fPIC": True}
|
||||
generators = "cmake"
|
||||
exports = "LICENSE.txt"
|
||||
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]
|
||||
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"]
|
||||
|
||||
def _inject_magic_lines(self):
|
||||
"""Inject Conan setup in cmake file to solve exteral dependencies.
|
||||
def source(self):
|
||||
"""Wrap the original CMake file to call conan_basic_setup
|
||||
"""
|
||||
conan_magic_lines = '''project(FlatBuffers)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
'''
|
||||
tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)
|
||||
shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt")
|
||||
shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
|
||||
|
||||
def config_options(self):
|
||||
"""Remove fPIC option on Windows platform
|
||||
"""
|
||||
if self.settings.os == "Windows":
|
||||
self.options.remove("fPIC")
|
||||
|
||||
def configure_cmake(self):
|
||||
"""Create CMake instance and execute configure step
|
||||
"""
|
||||
cmake = CMake(self)
|
||||
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
|
||||
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
|
||||
cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared
|
||||
cmake.configure()
|
||||
return cmake
|
||||
|
||||
def build(self):
|
||||
"""Configure, build and install FlatBuffers using CMake.
|
||||
"""
|
||||
self._inject_magic_lines()
|
||||
cmake = CMake(self)
|
||||
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
|
||||
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
|
||||
cmake.configure()
|
||||
cmake = self.configure_cmake()
|
||||
cmake.build()
|
||||
cmake.install()
|
||||
|
||||
def package(self):
|
||||
"""Copy Flatbuffers' artifacts to package folder
|
||||
"""
|
||||
cmake = self.configure_cmake()
|
||||
cmake.install()
|
||||
self.copy(pattern="LICENSE.txt", dst="licenses")
|
||||
self.copy(pattern="FindFlatBuffers.cmake", dst=os.path.join("lib", "cmake", "flatbuffers"), src="CMake")
|
||||
self.copy(pattern="flathash*", dst="bin", src="bin")
|
||||
self.copy(pattern="flatc*", dst="bin", src="bin")
|
||||
if self.settings.os == "Windows" and self.options.shared:
|
||||
if self.settings.compiler == "Visual Studio":
|
||||
shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name),
|
||||
os.path.join(self.package_folder, "bin", "%s.dll" % self.name))
|
||||
elif self.settings.compiler == "gcc":
|
||||
shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name),
|
||||
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name))
|
||||
|
||||
def package_info(self):
|
||||
"""Collect built libraries names and solve flatc path.
|
||||
"""
|
||||
self.cpp_info.libs = tools.collect_libs(self)
|
||||
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
|
||||
self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")
|
||||
|
||||
14
dart/CHANGELOG.md
Normal file
14
dart/CHANGELOG.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.9.2
|
||||
|
||||
- Ensure `_writeString` adds enough padding to null terminate strings.
|
||||
|
||||
## 1.9.1
|
||||
|
||||
- Changed constant identifiers to be compatible with Dart 2.x
|
||||
- No longer supports Dart 1.x
|
||||
|
||||
## 1.9.0
|
||||
|
||||
- Initial release, supports Dart 1.x and many dev versions of Dart 2.x
|
||||
233
dart/LICENSE
Normal file
233
dart/LICENSE
Normal file
@@ -0,0 +1,233 @@
|
||||
The code in lib/flat_buffers.dart is based on code that was releases under the
|
||||
following license:
|
||||
|
||||
Copyright 2012, the Dart project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
To the extent permissible, the changes to that code and the other assets in
|
||||
this package are licensed under the Apache2 license:
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
13
dart/README.md
Normal file
13
dart/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# FlatBuffers for Dart
|
||||
|
||||
This package is used to read and write FlatBuffer files in Dart.
|
||||
|
||||
Most consumers will want to use the [`flatc`](https://github.com/google/flatbuffers)
|
||||
compiler to generate Dart code from a FlatBuffers IDL schema. For example, the
|
||||
`monster_my_game.sample_generated.dart` was generated with `flatc` from
|
||||
`monster.fbs` in the example folder. The generated classes can be used to read
|
||||
or write binary files that are interoperable with other languages and platforms
|
||||
supported by FlatBuffers, as illustrated in the `example.dart` in the
|
||||
examples folder.
|
||||
|
||||
Additional documentation and examples are available [at the FlatBuffers site](https://google.github.io/flatbuffers/index.html)
|
||||
155
dart/example/example.dart
Normal file
155
dart/example/example.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2018 Dan Field. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_my_game.sample_generated.dart' as myGame;
|
||||
|
||||
// Example how to use FlatBuffers to create and read binary buffers.
|
||||
|
||||
void main() {
|
||||
builderTest();
|
||||
objectBuilderTest();
|
||||
}
|
||||
|
||||
void builderTest() {
|
||||
final builder = new fb.Builder(initialSize: 1024);
|
||||
final int weaponOneName = builder.writeString("Sword");
|
||||
final int weaponOneDamage = 3;
|
||||
|
||||
final int weaponTwoName = builder.writeString("Axe");
|
||||
final int weaponTwoDamage = 5;
|
||||
|
||||
final swordBuilder = new myGame.WeaponBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(weaponOneName)
|
||||
..addDamage(weaponOneDamage);
|
||||
final int sword = swordBuilder.finish();
|
||||
|
||||
final axeBuilder = new myGame.WeaponBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(weaponTwoName)
|
||||
..addDamage(weaponTwoDamage);
|
||||
final int axe = axeBuilder.finish();
|
||||
|
||||
// Serialize a name for our monster, called "Orc".
|
||||
final int name = builder.writeString('Orc');
|
||||
|
||||
// Create a list representing the inventory of the Orc. Each number
|
||||
// could correspond to an item that can be claimed after he is slain.
|
||||
final List<int> treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
final inventory = builder.writeListUint8(treasure);
|
||||
final weapons = builder.writeList([sword, axe]);
|
||||
|
||||
// Struct builders are very easy to reuse.
|
||||
final vec3Builder = new myGame.Vec3Builder(builder);
|
||||
|
||||
vec3Builder.finish(4.0, 5.0, 6.0);
|
||||
vec3Builder.finish(1.0, 2.0, 3.0);
|
||||
// Set his hit points to 300 and his mana to 150.
|
||||
final int hp = 300;
|
||||
final int mana = 150;
|
||||
|
||||
final monster = new myGame.MonsterBuilder(builder)
|
||||
..begin()
|
||||
..addNameOffset(name)
|
||||
..addInventoryOffset(inventory)
|
||||
..addWeaponsOffset(weapons)
|
||||
..addEquippedType(myGame.EquipmentTypeId.Weapon)
|
||||
..addEquippedOffset(axe)
|
||||
..addHp(hp)
|
||||
..addMana(mana)
|
||||
..addPos(vec3Builder.finish(1.0, 2.0, 3.0))
|
||||
..addColor(myGame.Color.Red);
|
||||
|
||||
final int monsteroff = monster.finish();
|
||||
final buffer = builder.finish(monsteroff);
|
||||
if (verify(buffer)) {
|
||||
print(
|
||||
"The FlatBuffer was successfully created with a builder and verified!");
|
||||
}
|
||||
}
|
||||
|
||||
void objectBuilderTest() {
|
||||
// Create the builder here so we can use it for both weapons and equipped
|
||||
// the actual data will only be written to the buffer once.
|
||||
var axe = new myGame.WeaponObjectBuilder(name: 'Axe', damage: 5);
|
||||
|
||||
var monsterBuilder = new myGame.MonsterObjectBuilder(
|
||||
pos: new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
|
||||
mana: 150,
|
||||
hp: 300,
|
||||
name: 'Orc',
|
||||
inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
color: myGame.Color.Red,
|
||||
weapons: [new myGame.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
|
||||
equippedType: myGame.EquipmentTypeId.Weapon,
|
||||
equipped: axe,
|
||||
);
|
||||
|
||||
var buffer = monsterBuilder.toBytes();
|
||||
|
||||
// We now have a FlatBuffer we can store on disk or send over a network.
|
||||
|
||||
// ** file/network code goes here :) **
|
||||
|
||||
// Instead, we're going to access it right away (as if we just received it).
|
||||
if (verify(buffer)) {
|
||||
print(
|
||||
"The FlatBuffer was successfully created with an object builder and verified!");
|
||||
}
|
||||
}
|
||||
|
||||
bool verify(List<int> buffer) {
|
||||
// Get access to the root:
|
||||
var monster = new myGame.Monster(buffer);
|
||||
|
||||
// Get and test some scalar types from the FlatBuffer.
|
||||
assert(monster.hp == 80);
|
||||
assert(monster.mana == 150); // default
|
||||
assert(monster.name == "MyMonster");
|
||||
|
||||
// Get and test a field of the FlatBuffer's `struct`.
|
||||
var pos = monster.pos;
|
||||
assert(pos != null);
|
||||
assert(pos.z == 3.0);
|
||||
|
||||
// Get a test an element from the `inventory` FlatBuffer's `vector`.
|
||||
var inv = monster.inventory;
|
||||
assert(inv != null);
|
||||
assert(inv.length == 10);
|
||||
assert(inv[9] == 9);
|
||||
|
||||
// Get and test the `weapons` FlatBuffers's `vector`.
|
||||
var expected_weapon_names = ["Sword", "Axe"];
|
||||
var expected_weapon_damages = [3, 5];
|
||||
var weps = monster.weapons;
|
||||
for (int i = 0; i < weps.length; i++) {
|
||||
assert(weps[i].name == expected_weapon_names[i]);
|
||||
assert(weps[i].damage == expected_weapon_damages[i]);
|
||||
}
|
||||
|
||||
// Get and test the `Equipment` union (`equipped` field).
|
||||
assert(monster.equippedType.value == myGame.EquipmentTypeId.Weapon.value);
|
||||
assert(monster.equippedType == myGame.EquipmentTypeId.Weapon);
|
||||
|
||||
assert(monster.equipped is myGame.Weapon);
|
||||
var equipped = monster.equipped as myGame.Weapon;
|
||||
assert(equipped.name == "Axe");
|
||||
assert(equipped.damage == 5);
|
||||
|
||||
print(monster);
|
||||
return true;
|
||||
}
|
||||
440
dart/example/monster_my_game.sample_generated.dart
Normal file
440
dart/example/monster_my_game.sample_generated.dart
Normal file
@@ -0,0 +1,440 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, non_constant_identifier_names
|
||||
|
||||
library my_game.sample;
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
|
||||
class Color {
|
||||
final int value;
|
||||
const Color._(this.value);
|
||||
|
||||
factory Color.fromValue(int value) {
|
||||
if (value == null) return null;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum Color');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 2;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Color Red = const Color._(0);
|
||||
static const Color Green = const Color._(1);
|
||||
static const Color Blue = const Color._(2);
|
||||
static get values => {0: Red,1: Green,2: Blue,};
|
||||
|
||||
static const fb.Reader<Color> reader = const _ColorReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Color{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _ColorReader extends fb.Reader<Color> {
|
||||
const _ColorReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
Color read(fb.BufferContext bc, int offset) =>
|
||||
new Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class EquipmentTypeId {
|
||||
final int value;
|
||||
const EquipmentTypeId._(this.value);
|
||||
|
||||
factory EquipmentTypeId.fromValue(int value) {
|
||||
if (value == null) return null;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum EquipmentTypeId');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 1;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const EquipmentTypeId NONE = const EquipmentTypeId._(0);
|
||||
static const EquipmentTypeId Weapon = const EquipmentTypeId._(1);
|
||||
static get values => {0: NONE,1: Weapon,};
|
||||
|
||||
static const fb.Reader<EquipmentTypeId> reader = const _EquipmentTypeIdReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EquipmentTypeId{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _EquipmentTypeIdReader extends fb.Reader<EquipmentTypeId> {
|
||||
const _EquipmentTypeIdReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
EquipmentTypeId read(fb.BufferContext bc, int offset) =>
|
||||
new EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Vec3 {
|
||||
Vec3._(this._bc, this._bcOffset);
|
||||
|
||||
static const fb.Reader<Vec3> reader = const _Vec3Reader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0);
|
||||
double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4);
|
||||
double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Vec3{x: $x, y: $y, z: $z}';
|
||||
}
|
||||
}
|
||||
|
||||
class _Vec3Reader extends fb.StructReader<Vec3> {
|
||||
const _Vec3Reader();
|
||||
|
||||
@override
|
||||
int get size => 12;
|
||||
|
||||
@override
|
||||
Vec3 createObject(fb.BufferContext bc, int offset) =>
|
||||
new Vec3._(bc, offset);
|
||||
}
|
||||
|
||||
class Vec3Builder {
|
||||
Vec3Builder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
int finish(double x, double y, double z) {
|
||||
fbBuilder.putFloat32(z);
|
||||
fbBuilder.putFloat32(y);
|
||||
fbBuilder.putFloat32(x);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
final double _x;
|
||||
final double _y;
|
||||
final double _z;
|
||||
|
||||
Vec3ObjectBuilder({
|
||||
double x,
|
||||
double y,
|
||||
double z,
|
||||
})
|
||||
: _x = x,
|
||||
_y = y,
|
||||
_z = z;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.putFloat32(_z);
|
||||
fbBuilder.putFloat32(_y);
|
||||
fbBuilder.putFloat32(_x);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
}
|
||||
}
|
||||
class Monster {
|
||||
Monster._(this._bc, this._bcOffset);
|
||||
factory Monster(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
Vec3 get pos => Vec3.reader.vTableGet(_bc, _bcOffset, 4, null);
|
||||
int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150);
|
||||
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null);
|
||||
List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null);
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
|
||||
List<Weapon> get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGet(_bc, _bcOffset, 18, null);
|
||||
EquipmentTypeId get equippedType => new EquipmentTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 20, null));
|
||||
dynamic get equipped {
|
||||
switch (equippedType?.value) {
|
||||
case 1: return Weapon.reader.vTableGet(_bc, _bcOffset, 22, null);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
List<Vec3> get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGet(_bc, _bcOffset, 24, null);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, weapons: $weapons, equippedType: $equippedType, equipped: $equipped, path: $path}';
|
||||
}
|
||||
}
|
||||
|
||||
class _MonsterReader extends fb.TableReader<Monster> {
|
||||
const _MonsterReader();
|
||||
|
||||
@override
|
||||
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||
new Monster._(bc, offset);
|
||||
}
|
||||
|
||||
class MonsterBuilder {
|
||||
MonsterBuilder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable();
|
||||
}
|
||||
|
||||
int addPos(int offset) {
|
||||
fbBuilder.addStruct(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addMana(int mana) {
|
||||
fbBuilder.addInt16(1, mana);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addHp(int hp) {
|
||||
fbBuilder.addInt16(2, hp);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addNameOffset(int offset) {
|
||||
fbBuilder.addOffset(3, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addInventoryOffset(int offset) {
|
||||
fbBuilder.addOffset(5, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addColor(Color color) {
|
||||
fbBuilder.addInt8(6, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addWeaponsOffset(int offset) {
|
||||
fbBuilder.addOffset(7, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addEquippedType(EquipmentTypeId equippedType) {
|
||||
fbBuilder.addUint8(8, equippedType?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addEquippedOffset(int offset) {
|
||||
fbBuilder.addOffset(9, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addPathOffset(int offset) {
|
||||
fbBuilder.addOffset(10, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final Vec3ObjectBuilder _pos;
|
||||
final int _mana;
|
||||
final int _hp;
|
||||
final String _name;
|
||||
final List<int> _inventory;
|
||||
final Color _color;
|
||||
final List<WeaponObjectBuilder> _weapons;
|
||||
final EquipmentTypeId _equippedType;
|
||||
final dynamic _equipped;
|
||||
final List<Vec3ObjectBuilder> _path;
|
||||
|
||||
MonsterObjectBuilder({
|
||||
Vec3ObjectBuilder pos,
|
||||
int mana,
|
||||
int hp,
|
||||
String name,
|
||||
List<int> inventory,
|
||||
Color color,
|
||||
List<WeaponObjectBuilder> weapons,
|
||||
EquipmentTypeId equippedType,
|
||||
dynamic equipped,
|
||||
List<Vec3ObjectBuilder> path,
|
||||
})
|
||||
: _pos = pos,
|
||||
_mana = mana,
|
||||
_hp = hp,
|
||||
_name = name,
|
||||
_inventory = inventory,
|
||||
_color = color,
|
||||
_weapons = weapons,
|
||||
_equippedType = equippedType,
|
||||
_equipped = equipped,
|
||||
_path = path;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
final int nameOffset = fbBuilder.writeString(_name);
|
||||
final int inventoryOffset = _inventory?.isNotEmpty == true
|
||||
? fbBuilder.writeListUint8(_inventory)
|
||||
: null;
|
||||
final int weaponsOffset = _weapons?.isNotEmpty == true
|
||||
? fbBuilder.writeList(_weapons.map((b) => b.getOrCreateOffset(fbBuilder)).toList())
|
||||
: null;
|
||||
final int equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
|
||||
final int pathOffset = _path?.isNotEmpty == true
|
||||
? fbBuilder.writeListOfStructs(_path)
|
||||
: null;
|
||||
|
||||
fbBuilder.startTable();
|
||||
if (_pos != null) {
|
||||
fbBuilder.addStruct(0, _pos.finish(fbBuilder));
|
||||
}
|
||||
fbBuilder.addInt16(1, _mana);
|
||||
fbBuilder.addInt16(2, _hp);
|
||||
if (nameOffset != null) {
|
||||
fbBuilder.addOffset(3, nameOffset);
|
||||
}
|
||||
if (inventoryOffset != null) {
|
||||
fbBuilder.addOffset(5, inventoryOffset);
|
||||
}
|
||||
fbBuilder.addInt8(6, _color?.value);
|
||||
if (weaponsOffset != null) {
|
||||
fbBuilder.addOffset(7, weaponsOffset);
|
||||
}
|
||||
fbBuilder.addUint8(8, _equippedType?.value);
|
||||
if (equippedOffset != null) {
|
||||
fbBuilder.addOffset(9, equippedOffset);
|
||||
}
|
||||
if (pathOffset != null) {
|
||||
fbBuilder.addOffset(10, pathOffset);
|
||||
}
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
}
|
||||
}
|
||||
class Weapon {
|
||||
Weapon._(this._bc, this._bcOffset);
|
||||
factory Weapon(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Weapon> reader = const _WeaponReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 4, null);
|
||||
int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, null);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Weapon{name: $name, damage: $damage}';
|
||||
}
|
||||
}
|
||||
|
||||
class _WeaponReader extends fb.TableReader<Weapon> {
|
||||
const _WeaponReader();
|
||||
|
||||
@override
|
||||
Weapon createObject(fb.BufferContext bc, int offset) =>
|
||||
new Weapon._(bc, offset);
|
||||
}
|
||||
|
||||
class WeaponBuilder {
|
||||
WeaponBuilder(this.fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
}
|
||||
|
||||
final fb.Builder fbBuilder;
|
||||
|
||||
void begin() {
|
||||
fbBuilder.startTable();
|
||||
}
|
||||
|
||||
int addNameOffset(int offset) {
|
||||
fbBuilder.addOffset(0, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addDamage(int damage) {
|
||||
fbBuilder.addInt16(1, damage);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class WeaponObjectBuilder extends fb.ObjectBuilder {
|
||||
final String _name;
|
||||
final int _damage;
|
||||
|
||||
WeaponObjectBuilder({
|
||||
String name,
|
||||
int damage,
|
||||
})
|
||||
: _name = name,
|
||||
_damage = damage;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
final int nameOffset = fbBuilder.writeString(_name);
|
||||
|
||||
fbBuilder.startTable();
|
||||
if (nameOffset != null) {
|
||||
fbBuilder.addOffset(0, nameOffset);
|
||||
}
|
||||
fbBuilder.addInt16(1, _damage);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
}
|
||||
}
|
||||
1241
dart/lib/flat_buffers.dart
Normal file
1241
dart/lib/flat_buffers.dart
Normal file
File diff suppressed because it is too large
Load Diff
20
tests/fuzzer/build_run_verifier_test.sh → dart/publish.sh
Normal file → Executable file
20
tests/fuzzer/build_run_verifier_test.sh → dart/publish.sh
Normal file → Executable file
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2018 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -13,8 +13,16 @@
|
||||
# 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.
|
||||
#
|
||||
# Note to pub consumers: this file is used to assist with publishing the
|
||||
# pub package from the flatbuffers repository and is not meant for general use.
|
||||
# As pub does not currently provide a way to exclude files, it is included here.
|
||||
|
||||
clang++ -fsanitize-coverage=edge -fsanitize=address -std=c++11 -stdlib=libstdc++ -I.. -I../../include flatbuffers_verifier_fuzzer.cc libFuzzer.a -o fuzz_verifier
|
||||
mkdir -p verifier_corpus
|
||||
cp ../*.mon verifier_corpus
|
||||
./fuzz_verifier verifier_corpus
|
||||
command -v pub >/dev/null 2>&1 || { echo >&2 "Require `pub` but it's not installed. Aborting."; exit 1; }
|
||||
|
||||
cp ../samples/monster.fbs example/
|
||||
cp ../tests/monster_test.fbs test/
|
||||
pub publish
|
||||
|
||||
rm example/monster.fbs
|
||||
rm test/monster_test.fbs
|
||||
20
dart/pubspec.yaml
Normal file
20
dart/pubspec.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
name: flat_buffers
|
||||
version: 1.12.0
|
||||
description: >
|
||||
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
|
||||
generate Dart classes for a FlatBuffers schema, and this library to assist with
|
||||
reading and writing the binary format.
|
||||
|
||||
Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
||||
authors:
|
||||
- Dan Field <dfield@gmail.com>
|
||||
- Konstantin Scheglov
|
||||
- Paul Berry
|
||||
homepage: https://github.com/google/flatbuffers
|
||||
documentation: https://google.github.io/flatbuffers/index.html
|
||||
dev_dependencies:
|
||||
test: ^1.3.0
|
||||
test_reflective_loader: ^0.1.4
|
||||
path: ^1.5.1
|
||||
environment:
|
||||
sdk: '>=2.0.0-dev.28.0 <3.0.0'
|
||||
573
dart/test/flat_buffers_test.dart
Normal file
573
dart/test/flat_buffers_test.dart
Normal file
@@ -0,0 +1,573 @@
|
||||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'package:flat_buffers/flat_buffers.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import './monster_test_my_game.example_generated.dart' as example;
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(BuilderTest);
|
||||
defineReflectiveTests(CheckOtherLangaugesData);
|
||||
});
|
||||
}
|
||||
|
||||
int indexToField(int index) {
|
||||
return (1 + 1 + index) * 2;
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CheckOtherLangaugesData {
|
||||
test_cppData() async {
|
||||
List<int> data = await new io.File(path.join(
|
||||
path.dirname(io.Platform.script.path),
|
||||
'monsterdata_test.mon',
|
||||
))
|
||||
.readAsBytes();
|
||||
example.Monster mon = new example.Monster(data);
|
||||
expect(mon.hp, 80);
|
||||
expect(mon.mana, 150);
|
||||
expect(mon.name, 'MyMonster');
|
||||
expect(mon.pos.x, 1.0);
|
||||
expect(mon.pos.y, 2.0);
|
||||
expect(mon.pos.z, 3.0);
|
||||
expect(mon.pos.test1, 3.0);
|
||||
expect(mon.pos.test2.value, 2.0);
|
||||
expect(mon.pos.test3.a, 5);
|
||||
expect(mon.pos.test3.b, 6);
|
||||
expect(mon.testType.value, example.AnyTypeId.Monster.value);
|
||||
expect(mon.test is example.Monster, true);
|
||||
final monster2 = mon.test as example.Monster;
|
||||
expect(monster2.name, "Fred");
|
||||
|
||||
expect(mon.inventory.length, 5);
|
||||
expect(mon.inventory.reduce((cur, next) => cur + next), 10);
|
||||
expect(mon.test4.length, 2);
|
||||
expect(
|
||||
mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100);
|
||||
expect(mon.testarrayofstring.length, 2);
|
||||
expect(mon.testarrayofstring[0], "test1");
|
||||
expect(mon.testarrayofstring[1], "test2");
|
||||
|
||||
// this will fail if accessing any field fails.
|
||||
expect(mon.toString(),
|
||||
'Monster{pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color{value: 2}, test3: Test{a: 5, b: 6}}, mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], color: Color{value: 8}, testType: AnyTypeId{value: 1}, test: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], testarrayofstring: [test1, test2], testarrayoftables: null, enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, testhashs64Fnv1: 7930699090847568257, testhashu64Fnv1: 7930699090847568257, testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, testhashs64Fnv1a: 4898026182817603057, testhashu64Fnv1a: 4898026182817603057, testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], vectorOfLongs: [1, 100, 10000, 1000000, 100000000], vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class BuilderTest {
|
||||
void test_monsterBuilder() {
|
||||
final fbBuilder = new Builder();
|
||||
final str = fbBuilder.writeString('MyMonster');
|
||||
|
||||
fbBuilder.writeString('test1');
|
||||
fbBuilder.writeString('test2');
|
||||
final testArrayOfString = fbBuilder.endStructVector(2);
|
||||
|
||||
final fred = fbBuilder.writeString('Fred');
|
||||
|
||||
final List<int> treasure = [0, 1, 2, 3, 4];
|
||||
final inventory = fbBuilder.writeListUint8(treasure);
|
||||
|
||||
final monBuilder = new example.MonsterBuilder(fbBuilder)
|
||||
..begin()
|
||||
..addNameOffset(fred);
|
||||
final mon2 = monBuilder.finish();
|
||||
|
||||
final testBuilder = new example.TestBuilder(fbBuilder);
|
||||
testBuilder.finish(10, 20);
|
||||
testBuilder.finish(30, 40);
|
||||
final test4 = fbBuilder.endStructVector(2);
|
||||
|
||||
|
||||
monBuilder
|
||||
..begin()
|
||||
..addPos(
|
||||
new example.Vec3Builder(fbBuilder).finish(
|
||||
1.0,
|
||||
2.0,
|
||||
3.0,
|
||||
3.0,
|
||||
example.Color.Green,
|
||||
() => testBuilder.finish(5, 6),
|
||||
),
|
||||
)
|
||||
..addHp(80)
|
||||
..addNameOffset(str)
|
||||
..addInventoryOffset(inventory)
|
||||
..addTestType(example.AnyTypeId.Monster)
|
||||
..addTestOffset(mon2)
|
||||
..addTest4Offset(test4)
|
||||
..addTestarrayofstringOffset(testArrayOfString);
|
||||
final mon = monBuilder.finish();
|
||||
fbBuilder.finish(mon);
|
||||
}
|
||||
|
||||
void test_error_addInt32_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
expect(() {
|
||||
builder.addInt32(0, 0);
|
||||
}, throwsStateError);
|
||||
}
|
||||
|
||||
void test_error_addOffset_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
expect(() {
|
||||
builder.addOffset(0, 0);
|
||||
}, throwsStateError);
|
||||
}
|
||||
|
||||
void test_error_endTable_withoutStartTable() {
|
||||
Builder builder = new Builder();
|
||||
expect(() {
|
||||
builder.endTable();
|
||||
}, throwsStateError);
|
||||
}
|
||||
|
||||
void test_error_startTable_duringTable() {
|
||||
Builder builder = new Builder();
|
||||
builder.startTable();
|
||||
expect(() {
|
||||
builder.startTable();
|
||||
}, throwsStateError);
|
||||
}
|
||||
|
||||
void test_error_writeString_duringTable() {
|
||||
Builder builder = new Builder();
|
||||
builder.startTable();
|
||||
expect(() {
|
||||
builder.writeString('12345');
|
||||
}, throwsStateError);
|
||||
}
|
||||
|
||||
void test_file_identifier() {
|
||||
Uint8List byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset, 'Az~ÿ');
|
||||
}
|
||||
// Convert byteList to a ByteData so that we can read data from it.
|
||||
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||
// First 4 bytes are an offset to the table data.
|
||||
int tableDataLoc = byteData.getUint32(0, Endian.little);
|
||||
// Next 4 bytes are the file identifier.
|
||||
expect(byteData.getUint8(4), 65); // 'a'
|
||||
expect(byteData.getUint8(5), 122); // 'z'
|
||||
expect(byteData.getUint8(6), 126); // '~'
|
||||
expect(byteData.getUint8(7), 255); // 'ÿ'
|
||||
// First 4 bytes of the table data are a backwards offset to the vtable.
|
||||
int vTableLoc = tableDataLoc -
|
||||
byteData.getInt32(tableDataLoc, Endian.little);
|
||||
// First 2 bytes of the vtable are the size of the vtable in bytes, which
|
||||
// should be 4.
|
||||
expect(byteData.getUint16(vTableLoc, Endian.little), 4);
|
||||
// Next 2 bytes are the size of the object in bytes (including the vtable
|
||||
// pointer), which should be 4.
|
||||
expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
|
||||
}
|
||||
|
||||
void test_low() {
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
expect((builder..putUint8(1)).lowFinish(), [1]);
|
||||
expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(3)).lowFinish(),
|
||||
[0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(4)).lowFinish(),
|
||||
[0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint8(5)).lowFinish(),
|
||||
[0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
expect((builder..putUint32(6)).lowFinish(),
|
||||
[6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||
}
|
||||
|
||||
void test_table_default() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
builder.addInt32(0, 10, 10);
|
||||
builder.addInt32(1, 20, 10);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buffer = new BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buffer.derefObject(0);
|
||||
// was not written, so uses the new default value
|
||||
expect(
|
||||
const Int32Reader()
|
||||
.vTableGet(buffer, objectOffset, indexToField(0), 15),
|
||||
15);
|
||||
// has the written value
|
||||
expect(
|
||||
const Int32Reader()
|
||||
.vTableGet(buffer, objectOffset, indexToField(1), 15),
|
||||
20);
|
||||
}
|
||||
|
||||
void test_table_format() {
|
||||
Uint8List byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
builder.startTable();
|
||||
builder.addInt32(0, 10);
|
||||
builder.addInt32(1, 20);
|
||||
builder.addInt32(2, 30);
|
||||
byteList = builder.finish(builder.endTable());
|
||||
}
|
||||
// Convert byteList to a ByteData so that we can read data from it.
|
||||
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||
// First 4 bytes are an offset to the table data.
|
||||
int tableDataLoc = byteData.getUint32(0, Endian.little);
|
||||
// First 4 bytes of the table data are a backwards offset to the vtable.
|
||||
int vTableLoc = tableDataLoc -
|
||||
byteData.getInt32(tableDataLoc, Endian.little);
|
||||
// First 2 bytes of the vtable are the size of the vtable in bytes, which
|
||||
// should be 10.
|
||||
expect(byteData.getUint16(vTableLoc, Endian.little), 10);
|
||||
// Next 2 bytes are the size of the object in bytes (including the vtable
|
||||
// pointer), which should be 16.
|
||||
expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
|
||||
// Remaining 6 bytes are the offsets within the object where the ints are
|
||||
// located.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int offset =
|
||||
byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
|
||||
expect(byteData.getInt32(tableDataLoc + offset, Endian.little),
|
||||
10 + 10 * i);
|
||||
}
|
||||
}
|
||||
|
||||
void test_table_string() {
|
||||
String latinString = 'test';
|
||||
String unicodeString = 'Проба пера';
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int latinStringOffset = builder.writeString(latinString);
|
||||
int unicodeStringOffset = builder.writeString(unicodeString);
|
||||
builder.startTable();
|
||||
builder.addOffset(0, latinStringOffset);
|
||||
builder.addOffset(1, unicodeStringOffset);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buf.derefObject(0);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)),
|
||||
latinString);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)),
|
||||
unicodeString);
|
||||
}
|
||||
|
||||
void test_table_types() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int stringOffset = builder.writeString('12345');
|
||||
builder.startTable();
|
||||
builder.addBool(0, true);
|
||||
builder.addInt8(1, 10);
|
||||
builder.addInt32(2, 20);
|
||||
builder.addOffset(3, stringOffset);
|
||||
builder.addInt32(4, 40);
|
||||
builder.addUint32(5, 0x9ABCDEF0);
|
||||
builder.addUint8(6, 0x9A);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
int objectOffset = buf.derefObject(0);
|
||||
expect(
|
||||
const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true);
|
||||
expect(
|
||||
const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10);
|
||||
expect(
|
||||
const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20);
|
||||
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)),
|
||||
'12345');
|
||||
expect(
|
||||
const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40);
|
||||
expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)),
|
||||
0x9ABCDEF0);
|
||||
expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)),
|
||||
0x9A);
|
||||
}
|
||||
|
||||
void test_writeList_of_Uint32() {
|
||||
List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint32(values);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(4));
|
||||
expect(items, orderedEquals(values));
|
||||
}
|
||||
|
||||
void test_writeList_ofBool() {
|
||||
void verifyListBooleans(int len, List<int> trueBits) {
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
List<bool> values = new List<bool>.filled(len, false);
|
||||
for (int bit in trueBits) {
|
||||
values[bit] = true;
|
||||
}
|
||||
int offset = builder.writeListBool(values);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<bool> items = const BoolListReader().read(buf, 0);
|
||||
expect(items, hasLength(len));
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
|
||||
}
|
||||
}
|
||||
|
||||
verifyListBooleans(0, <int>[]);
|
||||
verifyListBooleans(1, <int>[]);
|
||||
verifyListBooleans(1, <int>[0]);
|
||||
verifyListBooleans(31, <int>[0, 1]);
|
||||
verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
|
||||
verifyListBooleans(31, <int>[0, 30]);
|
||||
verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
|
||||
verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
|
||||
verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
|
||||
verifyListBooleans(63, <int>[]);
|
||||
verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
|
||||
verifyListBooleans(63, new List<int>.generate(63, (i) => i));
|
||||
verifyListBooleans(64, <int>[]);
|
||||
verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
|
||||
verifyListBooleans(64, <int>[1, 2, 62]);
|
||||
verifyListBooleans(64, <int>[0, 1, 2, 63]);
|
||||
verifyListBooleans(64, new List<int>.generate(64, (i) => i));
|
||||
verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
|
||||
}
|
||||
|
||||
void test_writeList_ofInt32() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
|
||||
}
|
||||
|
||||
void test_writeList_ofFloat64() {
|
||||
List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListFloat64(values);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<double> items = const Float64ListReader().read(buf, 0);
|
||||
|
||||
expect(items, hasLength(values.length));
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
expect(values[i], closeTo(items[i], .001));
|
||||
}
|
||||
}
|
||||
|
||||
void test_writeList_ofFloat32() {
|
||||
List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
|
||||
// write
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListFloat32(values);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<double> items = const Float32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
expect(values[i], closeTo(items[i], .001));
|
||||
}
|
||||
}
|
||||
|
||||
void test_writeList_ofObjects() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
// write the object #1
|
||||
int object1;
|
||||
{
|
||||
builder.startTable();
|
||||
builder.addInt32(0, 10);
|
||||
builder.addInt32(1, 20);
|
||||
object1 = builder.endTable();
|
||||
}
|
||||
// write the object #1
|
||||
int object2;
|
||||
{
|
||||
builder.startTable();
|
||||
builder.addInt32(0, 100);
|
||||
builder.addInt32(1, 200);
|
||||
object2 = builder.endTable();
|
||||
}
|
||||
// write the list
|
||||
int offset = builder.writeList([object1, object2]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<TestPointImpl> items =
|
||||
const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0);
|
||||
expect(items, hasLength(2));
|
||||
expect(items[0].x, 10);
|
||||
expect(items[0].y, 20);
|
||||
expect(items[1].x, 100);
|
||||
expect(items[1].y, 200);
|
||||
}
|
||||
|
||||
void test_writeList_ofStrings_asRoot() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int str1 = builder.writeString('12345');
|
||||
int str2 = builder.writeString('ABC');
|
||||
int offset = builder.writeList([str1, str2]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<String> items =
|
||||
const ListReader<String>(const StringReader()).read(buf, 0);
|
||||
expect(items, hasLength(2));
|
||||
expect(items, contains('12345'));
|
||||
expect(items, contains('ABC'));
|
||||
}
|
||||
|
||||
void test_writeList_ofStrings_inObject() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int listOffset = builder.writeList(
|
||||
[builder.writeString('12345'), builder.writeString('ABC')]);
|
||||
builder.startTable();
|
||||
builder.addOffset(0, listOffset);
|
||||
int offset = builder.endTable();
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0);
|
||||
List<String> items = reader.items;
|
||||
expect(items, hasLength(2));
|
||||
expect(items, contains('12345'));
|
||||
expect(items, contains('ABC'));
|
||||
}
|
||||
|
||||
void test_writeList_ofUint32() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||
expect(items, hasLength(3));
|
||||
expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
|
||||
}
|
||||
|
||||
void test_writeList_ofUint16() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint16(<int>[1, 2, 60000]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint16ListReader().read(buf, 0);
|
||||
expect(items, hasLength(3));
|
||||
expect(items, orderedEquals(<int>[1, 2, 60000]));
|
||||
}
|
||||
|
||||
void test_writeList_ofUint8() {
|
||||
List<int> byteList;
|
||||
{
|
||||
Builder builder = new Builder(initialSize: 0);
|
||||
int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]);
|
||||
byteList = builder.finish(offset);
|
||||
}
|
||||
// read and verify
|
||||
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||
List<int> items = const Uint8ListReader().read(buf, 0);
|
||||
expect(items, hasLength(5));
|
||||
expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A]));
|
||||
}
|
||||
}
|
||||
|
||||
class StringListWrapperImpl {
|
||||
final BufferContext bp;
|
||||
final int offset;
|
||||
|
||||
StringListWrapperImpl(this.bp, this.offset);
|
||||
|
||||
List<String> get items => const ListReader<String>(const StringReader())
|
||||
.vTableGet(bp, offset, indexToField(0));
|
||||
}
|
||||
|
||||
class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
|
||||
const StringListWrapperReader();
|
||||
|
||||
@override
|
||||
StringListWrapperImpl createObject(BufferContext object, int offset) {
|
||||
return new StringListWrapperImpl(object, offset);
|
||||
}
|
||||
}
|
||||
|
||||
class TestPointImpl {
|
||||
final BufferContext bp;
|
||||
final int offset;
|
||||
|
||||
TestPointImpl(this.bp, this.offset);
|
||||
|
||||
int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
|
||||
|
||||
int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
|
||||
}
|
||||
|
||||
class TestPointReader extends TableReader<TestPointImpl> {
|
||||
const TestPointReader();
|
||||
|
||||
@override
|
||||
TestPointImpl createObject(BufferContext object, int offset) {
|
||||
return new TestPointImpl(object, offset);
|
||||
}
|
||||
}
|
||||
62
dart/test/monster_test_my_game.example2_generated.dart
Normal file
62
dart/test/monster_test_my_game.example2_generated.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||
|
||||
library my_game.example2;
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
import 'include_test1_my_game.example2_generated.dart';
|
||||
import 'include_test2_my_game.example2_generated.dart';
|
||||
import './monster_test_my_game_generated.dart' as my_game;
|
||||
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||
|
||||
class Monster {
|
||||
Monster._(this._bc, this._bcOffset);
|
||||
factory Monster(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Monster{}';
|
||||
}
|
||||
}
|
||||
|
||||
class _MonsterReader extends fb.TableReader<Monster> {
|
||||
const _MonsterReader();
|
||||
|
||||
@override
|
||||
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||
new Monster._(bc, offset);
|
||||
}
|
||||
|
||||
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
MonsterObjectBuilder();
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
}
|
||||
}
|
||||
1542
dart/test/monster_test_my_game.example_generated.dart
Normal file
1542
dart/test/monster_test_my_game.example_generated.dart
Normal file
File diff suppressed because it is too large
Load Diff
62
dart/test/monster_test_my_game_generated.dart
Normal file
62
dart/test/monster_test_my_game_generated.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||
|
||||
library my_game;
|
||||
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
import 'include_test1_my_game_generated.dart';
|
||||
import 'include_test2_my_game_generated.dart';
|
||||
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
|
||||
class InParentNamespace {
|
||||
InParentNamespace._(this._bc, this._bcOffset);
|
||||
factory InParentNamespace(List<int> bytes) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||
return reader.read(rootRef, 0);
|
||||
}
|
||||
|
||||
static const fb.Reader<InParentNamespace> reader = const _InParentNamespaceReader();
|
||||
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InParentNamespace{}';
|
||||
}
|
||||
}
|
||||
|
||||
class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
|
||||
const _InParentNamespaceReader();
|
||||
|
||||
@override
|
||||
InParentNamespace createObject(fb.BufferContext bc, int offset) =>
|
||||
new InParentNamespace._(bc, offset);
|
||||
}
|
||||
|
||||
class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
|
||||
|
||||
InParentNamespaceObjectBuilder();
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
int finish(
|
||||
fb.Builder fbBuilder) {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
/// Convenience method to serialize to byte list.
|
||||
@override
|
||||
Uint8List toBytes([String fileIdentifier]) {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
int offset = finish(fbBuilder);
|
||||
return fbBuilder.finish(offset, fileIdentifier);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ you to build project/make files for any platform. For details on `cmake`, see
|
||||
<https://www.cmake.org>. In brief, depending on your platform, use one of
|
||||
e.g.:
|
||||
|
||||
cmake -G "Unix Makefiles"
|
||||
cmake -G "Visual Studio 10"
|
||||
cmake -G "Xcode"
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
|
||||
cmake -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Release
|
||||
cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
Then, build as normal for your platform. This should result in a `flatc`
|
||||
executable, essential for the next steps.
|
||||
@@ -29,6 +29,19 @@ Building should also produce two sample executables, `flatsamplebinary` and
|
||||
*Note that you MUST be in the root of the FlatBuffers distribution when you
|
||||
run 'flattests' or `flatsampletext`, or it will fail to load its files.*
|
||||
|
||||
## Building with VCPKG
|
||||
|
||||
You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install flatbuffers
|
||||
|
||||
The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Building for Android
|
||||
|
||||
There is a `flatbuffers/android` directory that contains all you need to build
|
||||
@@ -41,7 +54,7 @@ running the `android_sample.sh` script. Optionally, you may go to the
|
||||
`flatbuffers/samples/android` folder and build the sample with the
|
||||
`build_apk.sh` script or `ndk_build` / `adb` etc.
|
||||
|
||||
## Using FlatBuffers in your own projects.
|
||||
## Using FlatBuffers in your own projects
|
||||
|
||||
For C++, there is usually no runtime to compile, as the code consists of a
|
||||
single header, `include/flatbuffers/flatbuffers.h`. You should add the
|
||||
@@ -55,6 +68,39 @@ To see how to include FlatBuffers in any of our supported languages, please
|
||||
view the [Tutorial](@ref flatbuffers_guide_tutorial) and select your appropriate
|
||||
language using the radio buttons.
|
||||
|
||||
### Using in CMake-based projects
|
||||
If you want to use FlatBuffers in a project which already uses CMake, then a more
|
||||
robust and flexible approach is to build FlatBuffers as part of that project directly.
|
||||
This is done by making the FlatBuffers source code available to the main build
|
||||
and adding it using CMake's `add_subdirectory()` command. This has the
|
||||
significant advantage that the same compiler and linker settings are used
|
||||
between FlatBuffers and the rest of your project, so issues associated with using
|
||||
incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
particularly useful on Windows.
|
||||
|
||||
Suppose you put FlatBuffers source code in directory `${FLATBUFFERS_SRC_DIR}`.
|
||||
To build it as part of your project, add following code to your `CMakeLists.txt` file:
|
||||
```cmake
|
||||
# Add FlatBuffers directly to our build. This defines the `flatbuffers` target.
|
||||
add_subdirectory(${FLATBUFFERS_SRC_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# Now simply link against flatbuffers as needed to your already declared target.
|
||||
# The flatbuffers target carry header search path automatically if CMake > 2.8.11.
|
||||
target_link_libraries(own_project_target PRIVATE flatbuffers)
|
||||
```
|
||||
When build your project the `flatbuffers` library will be compiled and linked
|
||||
to a target as part of your project.
|
||||
|
||||
#### Override default depth limit of nested objects
|
||||
To override [the depth limit of recursion](@ref flatbuffers_guide_use_cpp),
|
||||
add this directive:
|
||||
```cmake
|
||||
set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
|
||||
```
|
||||
to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line.
|
||||
|
||||
#### For Google Play apps
|
||||
|
||||
For applications on Google Play that integrate this library, usage is tracked.
|
||||
|
||||
@@ -3,7 +3,7 @@ Using the schema compiler {#flatbuffers_guide_using_schema_compiler}
|
||||
|
||||
Usage:
|
||||
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] FILES...
|
||||
[ -- FILES...]
|
||||
|
||||
The files are read and parsed in order, and can contain either schemas
|
||||
@@ -23,6 +23,8 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--java`, `-j` : Generate Java code.
|
||||
|
||||
- `--kotlin`, `-k` : Generate Kotlin code.
|
||||
|
||||
- `--csharp`, `-n` : Generate C# code.
|
||||
|
||||
- `--go`, `-g` : Generate Go code.
|
||||
@@ -31,10 +33,22 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--js`, `-s`: Generate JavaScript code.
|
||||
|
||||
- `--ts`: Generate TypeScript code.
|
||||
|
||||
- `--php`: Generate PHP code.
|
||||
|
||||
- `--grpc`: Generate RPC stub code for GRPC.
|
||||
|
||||
- `--dart`: Generate Dart code.
|
||||
|
||||
- `--lua`: Generate Lua code.
|
||||
|
||||
- `--lobster`: Generate Lobster code.
|
||||
|
||||
- `--rust`, `-r` : Generate Rust code.
|
||||
|
||||
- `--swift`: Generate Swift code.
|
||||
|
||||
For any data input files:
|
||||
|
||||
- `--binary`, `-b` : If data is contained in this file, generate a
|
||||
@@ -62,6 +76,12 @@ Additional options:
|
||||
in quotes, no trailing commas in tables/vectors). By default, no quotes are
|
||||
required/generated, and trailing commas are allowed.
|
||||
|
||||
- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
|
||||
\x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
|
||||
|
||||
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
|
||||
By default, UTF-8 characters are printed as \uXXXX escapes."
|
||||
|
||||
- `--defaults-json` : Output fields whose value is equal to the default value
|
||||
when writing JSON text.
|
||||
|
||||
@@ -76,32 +96,73 @@ Additional options:
|
||||
statements) use `--no-includes.`
|
||||
|
||||
- `--no-includes` : Don't generate include statements for included schemas the
|
||||
generated file depends on (C++).
|
||||
generated file depends on (C++ / Python).
|
||||
|
||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
||||
FlatBuffers in-place.
|
||||
|
||||
`--gen-object-api` : Generate an additional object-based API. This API is
|
||||
- `--gen-onefile` : Generate single output file for C# and Go.
|
||||
|
||||
- `--gen-name-strings` : Generate type name functions for C++.
|
||||
|
||||
- `--gen-object-api` : Generate an additional object-based API. This API is
|
||||
more convenient for object construction and mutation than the base API,
|
||||
at the cost of efficiency (object allocation). Recommended only to be used
|
||||
if other options are insufficient.
|
||||
|
||||
- `--gen-onefile` : Generate single output file (useful for C#)
|
||||
- `--gen-compare` : Generate operator== for object-based API types.
|
||||
|
||||
- `--gen-all`: Generate not just code for the current schema files, but
|
||||
- `--gen-nullable` : Add Clang _Nullable for C++ pointer. or @Nullable for Java.
|
||||
|
||||
- `--gen-generated` : Add @Generated annotation for Java.
|
||||
|
||||
- `--gen-all` : Generate not just code for the current schema files, but
|
||||
for all files it includes as well. If the language uses a single file for
|
||||
output (by default the case for C++ and JS), all code will end up in
|
||||
this one file.
|
||||
|
||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||
- `--cpp-include` : Adds an #include in generated file
|
||||
|
||||
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
||||
|
||||
- `--cpp-str-type T` : Set object API string type (default std::string)
|
||||
T::c_str(), T::length() and T::empty() must be supported.
|
||||
The custom type also needs to be constructible from std::string (see the
|
||||
--cpp-str-flex-ctor option to change this behavior).
|
||||
|
||||
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
|
||||
std::string from Flatbuffers, but (char* + length). This allows efficient
|
||||
construction of custom string types, including zero-copy construction.
|
||||
|
||||
- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard.
|
||||
Supported `CPP_STD` values:
|
||||
* `c++0x` - generate code compatible with old compilers (VS2010).
|
||||
* `c++11` - use C++11 code generator (default);
|
||||
|
||||
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
||||
|
||||
- `--object-suffix` : Customise class suffix for C++ object-based API.
|
||||
|
||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||
|
||||
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
|
||||
instead of Node.js style exporting. Needed for compatibility with the
|
||||
Google closure compiler (useful for JS).
|
||||
|
||||
- `--es6-js-export` : Generates ECMAScript v6 style export definitions
|
||||
instead of Node.js style exporting. Useful when integrating flatbuffers
|
||||
with modern Javascript projects.
|
||||
|
||||
- `--go-namespace` : Generate the overrided namespace in Golang.
|
||||
|
||||
- `--go-import` : Generate the overrided import for flatbuffers in Golang.
|
||||
(default is "github.com/google/flatbuffers/go").
|
||||
|
||||
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
|
||||
This may crash flatc given a mismatched schema.
|
||||
|
||||
- `--size-prefixed` : Input binaries are size prefixed buffers.
|
||||
|
||||
- `--proto`: Expect input files to be .proto files (protocol buffers).
|
||||
Output the corresponding .fbs file.
|
||||
Currently supports: `package`, `message`, `enum`, nested declarations,
|
||||
@@ -109,6 +170,10 @@ Additional options:
|
||||
Does not support, but will skip without error: `option`, `service`,
|
||||
`extensions`, and most everything else.
|
||||
|
||||
- `--oneof-union` : Translate .proto oneofs to flatbuffer unions.
|
||||
|
||||
- `--grpc` : Generate GRPC interfaces for the specified languages.
|
||||
|
||||
- `--schema`: Serialize schemas instead of JSON (use with -b). This will
|
||||
output a binary version of the specified schema that itself corresponds
|
||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
||||
@@ -120,13 +185,40 @@ Additional options:
|
||||
an evolution of. Gives errors if not. Useful to check if schema
|
||||
modifications don't break schema evolution rules.
|
||||
|
||||
- `--conform-includes PATH` : Include path for the schema given with
|
||||
`--conform PATH`.
|
||||
|
||||
- `--filename-suffix SUFFIX` : The suffix appended to the generated
|
||||
file names. Default is '_generated'.
|
||||
|
||||
- `--filename-ext EXTENSION` : The extension appended to the generated
|
||||
file names. Default is language-specific (e.g. "h" for C++). This
|
||||
should not be used when multiple languages are specified.
|
||||
|
||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||
statements.
|
||||
|
||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
||||
|
||||
- `--no-fb-impor` : Don't include flatbuffers import statement for TypeScript.
|
||||
|
||||
- `--no-ts-reexpor` : Don't re-export imported dependencies for TypeScript.
|
||||
|
||||
- `--short-name` : Use short function names for JS and TypeScript.
|
||||
|
||||
- `--reflect-types` : Add minimal type reflection to code generation.
|
||||
|
||||
- `--reflect-names` : Add minimal type/name reflection.
|
||||
|
||||
- `--root-type T` : Select or override the default root_type.
|
||||
|
||||
- `--force-defaults` : Emit default values in binary output from JSON.
|
||||
|
||||
- `--force-empty` : When serializing from object API representation, force
|
||||
strings and vectors to empty rather than null.
|
||||
|
||||
- `--force-empty-vectors` : When serializing from object API representation, force
|
||||
vectors to empty rather than null.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -35,7 +35,7 @@ The test code itself is located in
|
||||
[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
|
||||
|
||||
This test file is built alongside `flatc`. To review how to build the project,
|
||||
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
||||
|
||||
To run the tests, execute `flattests` from the root `flatbuffers/` directory.
|
||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||
@@ -59,15 +59,18 @@ a `char *` array, which you pass to `GetMonster()`.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "monster_test_generate.h"
|
||||
#include <cstdio> // For printing and file access.
|
||||
#include <iostream> // C++ header file for printing
|
||||
#include <fstream> // C++ header file for file access
|
||||
|
||||
FILE* file = fopen("monsterdata_test.mon", "rb");
|
||||
fseek(file, 0L, SEEK_END);
|
||||
int length = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
|
||||
std::ifstream infile;
|
||||
infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in);
|
||||
infile.seekg(0,std::ios::end);
|
||||
int length = infile.tellg();
|
||||
infile.seekg(0,std::ios::beg);
|
||||
char *data = new char[length];
|
||||
fread(data, sizeof(char), length, file);
|
||||
fclose(file);
|
||||
infile.read(data, length);
|
||||
infile.close();
|
||||
|
||||
auto monster = GetMonster(data);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -78,13 +81,21 @@ If you look in your generated header, you'll see it has
|
||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
printf("%d\n", monster->hp()); // `80`
|
||||
printf("%d\n", monster->mana()); // default value of `150`
|
||||
printf("%s\n", monster->name()->c_str()); // "MyMonster"
|
||||
std::cout << "hp : " << monster->hp() << std::endl; // `80`
|
||||
std::cout << "mana : " << monster->mana() << std::endl; // default value of `150`
|
||||
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||
|
||||
The following attributes are supported:
|
||||
|
||||
- `shared` (on a field): For string fields, this enables the usage of string
|
||||
pooling (i.e. `CreateSharedString`) as default serialization behavior.
|
||||
|
||||
Specifically, `CreateXxxDirect` functions and `Pack` functions for object
|
||||
based API (see below) will use `CreateSharedString` to create strings.
|
||||
|
||||
## Object based API. {#flatbuffers_cpp_object_based_api}
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
@@ -103,7 +114,7 @@ To use:
|
||||
MonsterT monsterobj;
|
||||
|
||||
// Deserialize from buffer into object.
|
||||
UnPackTo(&monsterobj, flatbuffer);
|
||||
GetMonster(flatbuffer)->UnPackTo(&monsterobj);
|
||||
|
||||
// Update object directly like a C++ class instance.
|
||||
cout << monsterobj->name; // This is now a std::string!
|
||||
@@ -111,7 +122,7 @@ To use:
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb;
|
||||
Pack(fbb, &monsterobj);
|
||||
fbb.Finish(Monster::Pack(fbb, &monsterobj));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following attributes are specific to the object-based API code generation:
|
||||
@@ -127,10 +138,10 @@ The following attributes are specific to the object-based API code generation:
|
||||
verbatim in the class constructor initializer list for this member.
|
||||
|
||||
- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the
|
||||
object-based API all generated NativeTables that are allocated when unpacking
|
||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
||||
any std::vector that appears in a table defined with `native_custom_alloc`.
|
||||
This can be used to provide allocation from a pool for example, for faster
|
||||
object-based API all generated NativeTables that are allocated when unpacking
|
||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
||||
any std::vector that appears in a table defined with `native_custom_alloc`.
|
||||
This can be used to provide allocation from a pool for example, for faster
|
||||
unpacking when using the object-based API.
|
||||
|
||||
Minimal Example:
|
||||
@@ -148,8 +159,8 @@ The following attributes are specific to the object-based API code generation:
|
||||
typedef T *pointer;
|
||||
|
||||
template <class U>
|
||||
struct rebind {
|
||||
typedef custom_allocator<U> other;
|
||||
struct rebind {
|
||||
typedef custom_allocator<U> other;
|
||||
};
|
||||
|
||||
pointer allocate(const std::size_t n) {
|
||||
@@ -161,7 +172,7 @@ The following attributes are specific to the object-based API code generation:
|
||||
}
|
||||
|
||||
custom_allocator() throw() {}
|
||||
template <class U>
|
||||
template <class U>
|
||||
custom_allocator(const custom_allocator<U>&) throw() {}
|
||||
};
|
||||
|
||||
@@ -205,12 +216,15 @@ The following attributes are specific to the object-based API code generation:
|
||||
|
||||
Finally, the following top-level attribute
|
||||
|
||||
- native_include: "path" (at file level): Because the `native_type` attribute
|
||||
- `native_include`: "path" (at file level): Because the `native_type` attribute
|
||||
can be used to introduce types that are unknown to flatbuffers, it may be
|
||||
necessary to include "external" header files in the generated code. This
|
||||
attribute can be used to directly add an #include directive to the top of
|
||||
the generated code that includes the specified path directly.
|
||||
|
||||
- `force_align`: this attribute may not be respected in the object API,
|
||||
depending on the aligned of the allocator used with `new`.
|
||||
|
||||
# External references.
|
||||
|
||||
An additional feature of the object API is the ability to allow you to load
|
||||
@@ -237,8 +251,9 @@ influence this either globally (using the `--cpp-ptr-type` argument to
|
||||
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
|
||||
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
||||
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
||||
you, so you'll have to manage their lifecycles manually.
|
||||
|
||||
you, so you'll have to manage their lifecycles manually. To reference the
|
||||
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
||||
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
||||
|
||||
# Using different string type.
|
||||
|
||||
@@ -246,7 +261,18 @@ By default the object tree is built out of `std::string`, but you can
|
||||
influence this either globally (using the `--cpp-str-type` argument to
|
||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
||||
|
||||
The type must support T::c_str() and T::length() as member functions.
|
||||
The type must support T::c_str(), T::length() and T::empty() as member functions.
|
||||
|
||||
Further, the type must be constructible from std::string, as by default a
|
||||
std::string instance is constructed and then used to initialize the custom
|
||||
string type. This behavior impedes efficient and zero-copy construction of
|
||||
custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
|
||||
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
|
||||
so that the custom string type is constructed by passing the pointer and
|
||||
length of the FlatBuffers String. The custom string class will require a
|
||||
constructor in the following format: custom_str_class(const char *, size_t).
|
||||
Please note that the character array is not guaranteed to be NULL terminated,
|
||||
you should always use the provided size to determine end of string.
|
||||
|
||||
## Reflection (& Resizing)
|
||||
|
||||
@@ -400,6 +426,8 @@ it, this will provide you an easy way to use that data directly.
|
||||
(see the schema documentation for some specifics on the JSON format
|
||||
accepted).
|
||||
|
||||
Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
|
||||
|
||||
There are two ways to use text formats:
|
||||
|
||||
#### Using the compiler as a conversion tool
|
||||
@@ -451,7 +479,7 @@ include paths. If not specified, any include statements try to resolve from
|
||||
the current directory.
|
||||
|
||||
If there were any parsing errors, `Parse` will return `false`, and
|
||||
`Parser::err` contains a human readable error string with a line number
|
||||
`Parser::error_` contains a human readable error string with a line number
|
||||
etc, which you should present to the creator of that file.
|
||||
|
||||
After each JSON file, the `Parser::fbb` member variable is the
|
||||
@@ -492,4 +520,91 @@ needed to use unions.
|
||||
|
||||
To use scalars, simply wrap them in a struct.
|
||||
|
||||
## Depth limit of nested objects and stack-overflow control
|
||||
The parser of Flatbuffers schema or json-files is kind of recursive parser.
|
||||
To avoid stack-overflow problem the parser has a built-in limiter of
|
||||
recursion depth. Number of nested declarations in a schema or number of
|
||||
nested json-objects is limited. By default, this depth limit set to `64`.
|
||||
It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH`
|
||||
definition. This definition can be helpful for testing purposes or embedded
|
||||
applications. For details see [build](@ref flatbuffers_guide_building) of
|
||||
CMake-based projects.
|
||||
|
||||
## Dependence from C-locale {#flatbuffers_locale_cpp}
|
||||
The Flatbuffers [grammar](@ref flatbuffers grammar) uses ASCII
|
||||
character set for identifiers, alphanumeric literals, reserved words.
|
||||
|
||||
Internal implementation of the Flatbuffers depends from functions which
|
||||
depend from C-locale: `strtod()` or `strtof()`, for example.
|
||||
The library expects the dot `.` symbol as the separator of an integer
|
||||
part from the fractional part of a float number.
|
||||
Another separator symbols (`,` for example) will break the compatibility
|
||||
and may lead to an error while parsing a Flatbuffers schema or a json file.
|
||||
|
||||
The Standard C locale is a global resource, there is only one locale for
|
||||
the entire application. Some modern compilers and platforms have
|
||||
locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
|
||||
`strtoll_l`, `strtoull_l` to resolve this dependency.
|
||||
These functions use specified locale rather than the global or per-thread
|
||||
locale instead. They are part of POSIX-2008 but not part of the C/C++
|
||||
standard library, therefore, may be missing on some platforms.
|
||||
The Flatbuffers library try to detect these functions at configuration and
|
||||
compile time:
|
||||
- CMake `"CMakeLists.txt"`:
|
||||
- Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
|
||||
- Compile-time `"/include/base.h"`:
|
||||
- `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
|
||||
- `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
|
||||
|
||||
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
|
||||
set to `0` or `1`.
|
||||
To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
|
||||
or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
|
||||
|
||||
To test the compatibility of the Flatbuffers library with
|
||||
a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
||||
```sh
|
||||
>FLATBUFFERS_TEST_LOCALE="" ./flattests
|
||||
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
|
||||
```
|
||||
|
||||
## Support of floating-point numbers
|
||||
The Flatbuffers library assumes that a C++ compiler and a CPU are
|
||||
compatible with the `IEEE-754` floating-point standard.
|
||||
The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
|
||||
|
||||
### Support of hexadecimal and special floating-point numbers
|
||||
According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
|
||||
may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
|
||||
The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
|
||||
literals. The Flatbuffers library has a code to detect a compiler compatibility
|
||||
with the literals. If necessary conditions are met the preprocessor constant
|
||||
`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
|
||||
The support of floating-point literals will be limited at compile time
|
||||
if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
|
||||
In this case, schemas with hexadecimal or special literals cannot be used.
|
||||
|
||||
### Comparison of floating-point NaN values
|
||||
The floating-point `NaN` (`not a number`) is special value which
|
||||
representing an undefined or unrepresentable value.
|
||||
`NaN` may be explicitly assigned to variables, typically as a representation
|
||||
for missing values or may be a result of a mathematical operation.
|
||||
The `IEEE-754` defines two kind of `NaNs`:
|
||||
- Quiet NaNs, or `qNaNs`.
|
||||
- Signaling NaNs, or `sNaNs`.
|
||||
|
||||
According to the `IEEE-754`, a comparison with `NaN` always returns
|
||||
an unordered result even when compared with itself. As a result, a whole
|
||||
Flatbuffers object will be not equal to itself if has one or more `NaN`.
|
||||
Flatbuffers scalar fields that have the default value are not actually stored
|
||||
in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
|
||||
Scalar fields with `NaN` defaults break this behavior.
|
||||
If a schema has a lot of `NaN` defaults the Flatbuffers can override
|
||||
the unordered comparison by the ordered: `(NaN==NaN)->true`.
|
||||
This ordered comparison is enabled when compiling a program with the symbol
|
||||
`FLATBUFFERS_NAN_DEFAULTS` defined.
|
||||
Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
|
||||
if GCC or Clang used. These compilers have a compile-time implementation
|
||||
of `isnan` checking which MSVC does not.
|
||||
|
||||
<br>
|
||||
|
||||
175
docs/source/CsharpUsage.md
Normal file
175
docs/source/CsharpUsage.md
Normal file
@@ -0,0 +1,175 @@
|
||||
Use in C# {#flatbuffers_guide_use_c-sharp}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in C#, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including C#).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to C#.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers C-sharp code location
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers C-sharp libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers C# library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in C#.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in C#.
|
||||
|
||||
To use FlatBuffers in your own code, first generate C# classes from your
|
||||
schema with the `--csharp` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in C#:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `GetRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
using MyGame.Example;
|
||||
using FlatBuffers;
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
|
||||
|
||||
ByteBuffer bb = new ByteBuffer(data);
|
||||
Monster monster = Monster.GetRootAsMonster(bb);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
short hp = monster.Hp;
|
||||
Vec3 pos = monster.Pos;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C# code naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
emulate their behavior with vectors and binary search, which means you
|
||||
can have fast lookups directly from a FlatBuffer without having to unpack
|
||||
your data into a `Dictionary` or similar.
|
||||
|
||||
To use it:
|
||||
- Designate one of the fields in a table as the "key" field. You do this
|
||||
by setting the `key` attribute on this field, e.g.
|
||||
`name:string (key)`.
|
||||
You may only have one key field, and it must be of string or scalar type.
|
||||
- Write out tables of this type as usual, collect their offsets in an
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C#
|
||||
which will first sort all offsets such that the tables they refer to
|
||||
are sorted by the key field, then serialize it.
|
||||
- Now when you're accessing the FlatBuffer, you can use
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
speed to `Dictionary`, though may be faster because of better caching.
|
||||
`ByKey` only works if the vector has been sorted, it will
|
||||
likely not find elements if it hasn't been sorted.
|
||||
|
||||
## Text parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from C#, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
## Object based API
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
(requiring pre-order construction of all data, and making mutation harder).
|
||||
|
||||
For times when efficiency is less important a more convenient object based API
|
||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
||||
FlatBuffer into objects and standard System.Collections.Generic containers, allowing for convenient
|
||||
construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize from buffer into object.
|
||||
MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
|
||||
|
||||
// Update object directly like a C# class instance.
|
||||
Console.WriteLine(monsterobj.Name);
|
||||
monsterobj.Name = "Bob"; // Change the name.
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
||||
fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### Json Serialization
|
||||
|
||||
An additional feature of the object API is the ability to allow you to
|
||||
serialize & deserialize a JSON text.
|
||||
To use Json Serialization, add `--gen-json-serializer` option to `flatc` and
|
||||
add `Newtonsoft.Json` nuget package to csproj.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize MonsterT from json
|
||||
string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
|
||||
MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
|
||||
|
||||
// Serialize MonsterT to json
|
||||
string jsonText2 = mon.SerializeToJson();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Limitation
|
||||
* `hash` attribute currentry not supported.
|
||||
* NuGet package Dependency
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
|
||||
<br>
|
||||
108
docs/source/DartUsage.md
Normal file
108
docs/source/DartUsage.md
Normal file
@@ -0,0 +1,108 @@
|
||||
Use in Dart {#flatbuffers_guide_use_dart}
|
||||
===========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Dart, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
||||
to general FlatBuffers usage in all of the supported languages (including Dart).
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Dart.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Dart library code location
|
||||
|
||||
The code for the FlatBuffers Dart library can be found at
|
||||
`flatbuffers/dart`. You can browse the library code on the [FlatBuffers
|
||||
GitHub page](https://github.com/google/flatbuffers/tree/master/dart).
|
||||
|
||||
## Testing the FlatBuffers Dart library
|
||||
|
||||
The code to test the Dart library can be found at `flatbuffers/tests`.
|
||||
The test code itself is located in [dart_test.dart](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/dart_test.dart).
|
||||
|
||||
To run the tests, use the [DartTest.sh](https://github.com/google/flatbuffers/
|
||||
blob/master/tests/DartTest.sh) shell script.
|
||||
|
||||
*Note: The shell script requires the [Dart SDK](https://www.dartlang.org/tools/sdk)
|
||||
to be installed.*
|
||||
|
||||
## Using the FlatBuffers Dart library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Dart.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Dart.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Dart classes from your
|
||||
schema with the `--dart` option to `flatc`. Then you can include both FlatBuffers
|
||||
and the generated code to read or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Dart: First,
|
||||
include the library and generated code. Then read a FlatBuffer binary file into
|
||||
a `List<int>`, which you pass to the factory constructor for `Monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
import './monster_my_game.sample_generated.dart' as myGame;
|
||||
|
||||
List<int> data = await new io.File('monster.dat').readAsBytes();
|
||||
var monster = new myGame.Monster(data);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
||||
var hp = monster.hp;
|
||||
var pos = monster.pos;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Differences from the Dart SDK Front End flat_buffers
|
||||
|
||||
The work in this repository is signfiicantly based on the implementation used
|
||||
internally by the Dart SDK in the front end/analyzer package. Several
|
||||
significant changes have been made.
|
||||
|
||||
1. Support for packed boolean lists has been removed. This is not standard
|
||||
in other implementations and is not compatible with them. Do note that,
|
||||
like in the JavaScript implementation, __null values in boolean lists
|
||||
will be treated as false__. It is also still entirely possible to pack data
|
||||
in a single scalar field, but that would have to be done on the application
|
||||
side.
|
||||
2. The SDK implementation supports enums with regular Dart enums, which
|
||||
works if enums are always indexed at 1; however, FlatBuffers does not
|
||||
require that. This implementation uses specialized enum-like classes to
|
||||
ensure proper mapping from FlatBuffers to Dart and other platforms.
|
||||
3. The SDK implementation does not appear to support FlatBuffer structs or
|
||||
vectors of structs - it treated everything as a built-in scalar or a table.
|
||||
This implementation treats structs in a way that is compatible with other
|
||||
non-Dart implementations, and properly handles vectors of structs. Many of
|
||||
the methods prefixed with 'low' have been prepurposed to support this.
|
||||
4. The SDK implementation treats int64 and uint64 as float64s. This
|
||||
implementation does not. This may cause problems with JavaScript
|
||||
compatibility - however, it should be possible to use the JavaScript
|
||||
implementation, or to do a customized implementation that treats all 64 bit
|
||||
numbers as floats. Supporting the Dart VM and Flutter was a more important
|
||||
goal of this implementation. Support for 16 bit integers was also added.
|
||||
5. The code generation in this offers an "ObjectBuilder", which generates code
|
||||
very similar to the SDK classes that consume FlatBuffers, as well as Builder
|
||||
classes, which produces code which more closely resembles the builders in
|
||||
other languages. The ObjectBuilder classes are easier to use, at the cost of
|
||||
additional references allocated.
|
||||
|
||||
## Text Parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from Dart, though you could use the C++ parser through Dart Native Extensions.
|
||||
Please see the C++ documentation for more on text parsing (note that this is
|
||||
not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053)
|
||||
for the latest).
|
||||
|
||||
<br>
|
||||
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
|
||||
# Overview {#flatbuffers_overview}
|
||||
|
||||
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
||||
serialization library for C++, C#, C, Go, Java, JavaScript, TypeScript, PHP, and Python.
|
||||
serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
|
||||
It was originally created at Google for game development and other
|
||||
performance-critical applications.
|
||||
|
||||
@@ -51,7 +51,7 @@ under the Apache license, v2 (see LICENSE.txt).
|
||||
needed (faster and more memory efficient than other JSON
|
||||
parsers).
|
||||
|
||||
Java and Go code supports object-reuse. C# has efficient struct based
|
||||
Java, Kotlin and Go code supports object-reuse. C# has efficient struct based
|
||||
accessors.
|
||||
|
||||
- **Cross platform code with no dependencies** - C++ code will work
|
||||
@@ -108,7 +108,7 @@ sections provide a more in-depth usage guide.
|
||||
present for every object instance.
|
||||
|
||||
- Use `flatc` (the FlatBuffer compiler) to generate a C++ header (or
|
||||
Java/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
Java/Kotlin/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
serialized data. This header (say `mydata_generated.h`) only depends on
|
||||
`flatbuffers.h`, which defines the core functionality.
|
||||
|
||||
@@ -130,16 +130,28 @@ sections provide a more in-depth usage guide.
|
||||
- How to [write a schema](@ref flatbuffers_guide_writing_schema).
|
||||
- How to [use the generated C++ code](@ref flatbuffers_guide_use_cpp) in your
|
||||
own programs.
|
||||
- How to [use the generated Java/C# code](@ref flatbuffers_guide_use_java_c-sharp)
|
||||
- How to [use the generated Java code](@ref flatbuffers_guide_use_java)
|
||||
in your own programs.
|
||||
- How to [use the generated C# code](@ref flatbuffers_guide_use_c-sharp)
|
||||
in your own programs.
|
||||
- How to [use the generated Kotlin code](@ref flatbuffers_guide_use_kotlin)
|
||||
in your own programs.
|
||||
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
||||
own programs.
|
||||
- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
|
||||
own programs.
|
||||
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
|
||||
own programs.
|
||||
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
|
||||
own programs.
|
||||
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
|
||||
own programs.
|
||||
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
|
||||
own programs.
|
||||
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
|
||||
own programs.
|
||||
- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
|
||||
own programs.
|
||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
||||
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
||||
using FlatBuffers.
|
||||
@@ -155,6 +167,7 @@ sections provide a more in-depth usage guide.
|
||||
- [GitHub repository](http://github.com/google/flatbuffers)
|
||||
- [Landing page](http://google.github.io/flatbuffers)
|
||||
- [FlatBuffers Google Group](https://groups.google.com/forum/#!forum/flatbuffers)
|
||||
- [Discord](https://discord.gg/6qgKs3R) and [Gitter](https://gitter.im/lobster_programming_language/community) chat.
|
||||
- [FlatBuffers Issues Tracker](http://github.com/google/flatbuffers/issues)
|
||||
- Independent implementations & tools:
|
||||
- [FlatCC](https://github.com/dvidelabs/flatcc) Alternative FlatBuffers
|
||||
@@ -170,3 +183,6 @@ sections provide a more in-depth usage guide.
|
||||
- [FlatBuffers in Android](http://frogermcs.github.io/flatbuffers-in-android-introdution/)
|
||||
- [Parsing JSON to FlatBuffers in Java](http://frogermcs.github.io/json-parsing-with-flatbuffers-in-android/)
|
||||
- [FlatBuffers in Unity](http://exiin.com/blog/flatbuffers-for-unity-sample-code/)
|
||||
- [FlexBuffers C#](https://github.com/mzaks/FlexBuffers-CSharp) and
|
||||
[article](https://medium.com/@icex33/flexbuffers-for-unity3d-4d1ab5c53fbe?)
|
||||
on its use.
|
||||
|
||||
@@ -29,9 +29,7 @@ FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
|
||||
only use it if you need it.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
This is for C++, other languages may follow.
|
||||
# Usage in C++
|
||||
|
||||
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
|
||||
and `util.h`.
|
||||
@@ -98,10 +96,10 @@ allows a single type, and uses a bit less memory.
|
||||
`IndirectFloat` is an interesting feature that allows you to store values
|
||||
by offset rather than inline. Though that doesn't make any visible change
|
||||
to the user, the consequence is that large values (especially doubles or
|
||||
64 bit ints) that occur more than once can be shared. Another use case is
|
||||
inside of vectors, where the largest element makes up the size of all elements
|
||||
(e.g. a single double forces all elements to 64bit), so storing a lot of small
|
||||
integers together with a double is more efficient if the double is indirect.
|
||||
64 bit ints) that occur more than once can be shared (see ReuseValue).
|
||||
Another use case is inside of vectors, where the largest element makes
|
||||
up the size of all elements (e.g. a single double forces all elements to
|
||||
64bit), so storing a lot of small integers together with a double is more efficient if the double is indirect.
|
||||
|
||||
Accessing it:
|
||||
|
||||
@@ -122,6 +120,46 @@ map["unknown"].IsNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Usage in Java
|
||||
|
||||
Java implementation follows the C++ one, closely.
|
||||
|
||||
For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`,
|
||||
one could use the following code:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
|
||||
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
|
||||
int smap = builder.startMap();
|
||||
int svec = builder.startVector();
|
||||
builder.putInt(-100);
|
||||
builder.putString("Fred");
|
||||
builder.putFloat(4.0);
|
||||
builder.endVector("vec", svec, false, false);
|
||||
builder.putInt("foo", 100);
|
||||
builder.endMap(null, smap);
|
||||
ByteBuffer bb = builder.finish();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similarly, to read the data, just:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap();
|
||||
map.size(); // 2
|
||||
FlexBuffers.Vector vec = map.get("vec").asVector();
|
||||
vec.size(); // 3
|
||||
vec.get(0).asLong(); // -100;
|
||||
vec.get(1).asString(); // "Fred";
|
||||
vec.get(1).asLong(); // 0 (Number parsing failed).
|
||||
vec.get(2).asFloat(); // 4.0
|
||||
vec.get(2).asString().isEmpty(); // true (Wrong Type).
|
||||
vec.get(2).asString(); // "" (This still works though).
|
||||
vec.get(2).toString(); // "4.0" (Or have it converted).
|
||||
map.get("foo").asUInt(); // 100
|
||||
map.get("unknown").isNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Binary encoding
|
||||
|
||||
A description of how FlexBuffers are encoded is in the
|
||||
|
||||
@@ -10,11 +10,11 @@ include = `include` string\_constant `;`
|
||||
|
||||
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
||||
|
||||
attribute\_decl = `attribute` string\_constant `;`
|
||||
attribute\_decl = `attribute` ident | `"`ident`"` `;`
|
||||
|
||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||
|
||||
enum\_decl = ( `enum` ident [ `:` type ] | `union` ident ) metadata `{`
|
||||
enum\_decl = ( `enum` ident `:` type | `union` ident ) metadata `{`
|
||||
commasep( enumval\_decl ) `}`
|
||||
|
||||
root\_decl = `root_type` ident `;`
|
||||
@@ -49,11 +49,26 @@ file_extension_decl = `file_extension` string\_constant `;`
|
||||
|
||||
file_identifier_decl = `file_identifier` string\_constant `;`
|
||||
|
||||
integer\_constant = `-?[0-9]+` | `true` | `false`
|
||||
|
||||
float\_constant = `-?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?`
|
||||
|
||||
string\_constant = `\".*?\"`
|
||||
|
||||
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
||||
|
||||
`[:digit:]` = `[0-9]`
|
||||
|
||||
`[:xdigit:]` = `[0-9a-fA-F]`
|
||||
|
||||
dec\_integer\_constant = `[-+]?[:digit:]+`
|
||||
|
||||
hex\_integer\_constant = `[-+]?0[xX][:xdigit:]+`
|
||||
|
||||
integer\_constant = dec\_integer\_constant | hex\_integer\_constant
|
||||
|
||||
dec\_float\_constant = `[-+]?(([.][:digit:]+)|([:digit:]+[.][:digit:]*)|([:digit:]+))([eE][-+]?[:digit:]+)?`
|
||||
|
||||
hex\_float\_constant = `[-+]?0[xX](([.][:xdigit:]+)|([:xdigit:]+[.][:xdigit:]*)|([:xdigit:]+))([pP][-+]?[:digit:]+)`
|
||||
|
||||
special\_float\_constant = `[-+]?(nan|inf|infinity)`
|
||||
|
||||
float\_constant = decimal\_float\_constant | hexadecimal\_float\_constant | special\_float\_constant
|
||||
|
||||
boolean\_constant = `(true|false)` | (integer\_constant ? `true` : `false`)
|
||||
|
||||
@@ -15,6 +15,12 @@ all commonly used CPUs today. FlatBuffers will also work on big-endian
|
||||
machines, but will be slightly slower because of additional
|
||||
byte-swap intrinsics.
|
||||
|
||||
It is assumed that the following conditions are met, to ensure
|
||||
cross-platform interoperability:
|
||||
- The binary `IEEE-754` format is used for floating-point numbers.
|
||||
- The `two's complemented` representation is used for signed integers.
|
||||
- The endianness is the same for floating-point numbers as for integers.
|
||||
|
||||
On purpose, the format leaves a lot of details about where exactly
|
||||
things live in memory undefined, e.g. fields in a table can have any
|
||||
order, and objects to some extent can be stored in many orders. This is
|
||||
@@ -169,7 +175,7 @@ Unions share a lot with enums.
|
||||
Predeclare all data types since circular references between types are allowed
|
||||
(circular references between object are not, though).
|
||||
|
||||
MANUALLY_ALIGNED_STRUCT(4) Vec3 {
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 {
|
||||
private:
|
||||
float x_;
|
||||
float y_;
|
||||
@@ -183,7 +189,7 @@ Predeclare all data types since circular references between types are allowed
|
||||
float y() const { return flatbuffers::EndianScalar(y_); }
|
||||
float z() const { return flatbuffers::EndianScalar(z_); }
|
||||
};
|
||||
STRUCT_END(Vec3, 12);
|
||||
FLATBUFFERS_STRUCT_END(Vec3, 12);
|
||||
|
||||
These ugly macros do a couple of things: they turn off any padding the compiler
|
||||
might normally do, since we add padding manually (though none in this example),
|
||||
|
||||
@@ -1,41 +1,30 @@
|
||||
Use in Java/C# {#flatbuffers_guide_use_java_c-sharp}
|
||||
Use in Java {#flatbuffers_guide_use_java}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Java or C#, it should be noted that
|
||||
Before diving into the FlatBuffers usage in Java, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including both Java
|
||||
and C#). This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java and C#.
|
||||
general FlatBuffers usage in all of the supported languages (including Java).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Java and C-sharp code location
|
||||
|
||||
#### Java
|
||||
## FlatBuffers Java code location
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers Java and C-sharp libraries
|
||||
## Testing the FlatBuffers Java libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
#### Java
|
||||
|
||||
The test code for Java is located in [JavaTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/JavaTest.java).
|
||||
|
||||
@@ -47,31 +36,15 @@ system.
|
||||
*Note: These scripts require that [Java](https://www.oracle.com/java/index.html)
|
||||
is installed.*
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers Java (and C#) library
|
||||
## Using the FlatBuffers Java library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Java or C#.*
|
||||
example of how to use FlatBuffers in Java.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java and C#.
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--java` option to `flatc`. (Or for C# with `--csharp`).
|
||||
schema with the `--java` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
@@ -80,11 +53,6 @@ First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
*Note: The code here is written from the perspective of Java. Code for both
|
||||
languages is both generated and used in nearly the exact same way, with only
|
||||
minor differences. These differences are
|
||||
[explained in a section below](#differences_in_c-sharp).*
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
import MyGame.Example.*;
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
@@ -107,30 +75,6 @@ Now you can access the data from the `Monster monster`:
|
||||
Vec3 pos = monster.pos();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
<a name="differences_in_c-sharp">
|
||||
#### Differences in C-sharp
|
||||
</a>
|
||||
|
||||
C# code works almost identically to Java, with only a few minor differences.
|
||||
You can see an example of C# code in
|
||||
`tests/FlatBuffers.Test/FlatBuffersExampleTests.cs` or
|
||||
`samples/SampleBinary.cs`.
|
||||
|
||||
First of all, naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods as in Java.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
@@ -147,14 +91,12 @@ To use it:
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C# or
|
||||
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
|
||||
call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object).
|
||||
which will first sort all offsets such that the tables they refer to
|
||||
are sorted by the key field, then serialize it.
|
||||
- Now when you're accessing the FlatBuffer, you can use
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.testarrayoftablesByKey("Frodo")` in Java or
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
`monster.testarrayoftablesByKey("Frodo")`.
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
@@ -165,7 +107,7 @@ To use it:
|
||||
## Text parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from Java or C#, though you could use the C++ parser through native call
|
||||
from Java, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
84
docs/source/KotlinUsage.md
Normal file
84
docs/source/KotlinUsage.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Use in Kotlin {#flatbuffers_guide_use_kotlin}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Kotlin, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including K).
|
||||
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## Kotlin and FlatBuffers Java code location
|
||||
|
||||
Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported.
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
## Testing FlatBuffers Kotlin
|
||||
|
||||
The test code for Java is located in [KotlinTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/KotlinTest.kt).
|
||||
|
||||
To run the tests, use [KotlinTest.sh](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/KotlinTest.sh) shell script.
|
||||
|
||||
*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.*
|
||||
|
||||
## Using the FlatBuffers Kotlin library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Kotlin.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Kotlin.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--kotlin` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Kotlin:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
import MyGame.Example.*
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use {
|
||||
val temp = ByteArray(it.length().toInt())
|
||||
it.readFully(temp)
|
||||
temp
|
||||
}
|
||||
|
||||
val bb = ByteBuffer.wrap(data)
|
||||
val monster = Monster.getRootAsMonster(bb)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
val hp = monster.hp
|
||||
val pos = monster.pos!!;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
## Differences between Kotlin and Java code
|
||||
|
||||
Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html).
|
||||
|
||||
The most obvious ones are:
|
||||
|
||||
* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html)
|
||||
* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects)
|
||||
85
docs/source/LobsterUsage.md
Normal file
85
docs/source/LobsterUsage.md
Normal file
@@ -0,0 +1,85 @@
|
||||
Use in Lobster {#flatbuffers_guide_use_lobster}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Lobster, it should be noted that the
|
||||
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
|
||||
FlatBuffers usage in all of the supported languages (including Lobster). This
|
||||
page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Lobster.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Lobster library code location
|
||||
|
||||
The code for the FlatBuffers Lobster library can be found at
|
||||
`flatbuffers/lobster`. You can browse the library code on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
lobster).
|
||||
|
||||
## Testing the FlatBuffers Lobster library
|
||||
|
||||
The code to test the Lobster library can be found at `flatbuffers/tests`.
|
||||
The test code itself is located in [lobstertest.lobster](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/lobstertest.lobster).
|
||||
|
||||
To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself,
|
||||
go to the [Lobster homepage](http://strlen.com/lobster) or
|
||||
[github](https://github.com/aardappel/lobster) to learn how to build it for your
|
||||
platform.
|
||||
|
||||
## Using the FlatBuffers Lobster library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Lobster.*
|
||||
|
||||
There is support for both reading and writing FlatBuffers in Lobster.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Lobster classes from your
|
||||
schema with the `--lobster` option to `flatc`. Then you can include both
|
||||
FlatBuffers and the generated code to read or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Lobster:
|
||||
First, import the library and the generated code. Then read a FlatBuffer binary
|
||||
file into a string, which you pass to the `GetRootAsMonster` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
||||
include "monster_generated.lobster"
|
||||
|
||||
let fb = read_file("monsterdata_test.mon")
|
||||
assert fb
|
||||
let monster = MyGame_Example_GetRootAsMonster(fb)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
||||
let hp = monster.hp
|
||||
let pos = monster.pos
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As you can see, even though `hp` and `pos` are functions that access FlatBuffer
|
||||
data in-place in the string buffer, they appear as field accesses.
|
||||
|
||||
## Speed
|
||||
|
||||
Using FlatBuffers in Lobster should be relatively fast, as the implementation
|
||||
makes use of native support for writing binary values, and access of vtables.
|
||||
Both generated code and the runtime library are therefore small and fast.
|
||||
|
||||
Actual speed will depend on wether you use Lobster as bytecode VM or compiled to
|
||||
C++.
|
||||
|
||||
## Text Parsing
|
||||
|
||||
Lobster has full support for parsing JSON into FlatBuffers, or generating
|
||||
JSON from FlatBuffers. See `samples/sample_test.lobster` for an example.
|
||||
|
||||
This uses the C++ parser and generator underneath, so should be both fast and
|
||||
conformant.
|
||||
|
||||
<br>
|
||||
81
docs/source/LuaUsage.md
Normal file
81
docs/source/LuaUsage.md
Normal file
@@ -0,0 +1,81 @@
|
||||
Use in Lua {#flatbuffers_guide_use_lua}
|
||||
=============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Lua, it should be noted that the
|
||||
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
|
||||
FlatBuffers usage in all of the supported languages (including Lua). This
|
||||
page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Lua.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Lua library code location
|
||||
|
||||
The code for the FlatBuffers Lua library can be found at
|
||||
`flatbuffers/lua`. You can browse the library code on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua).
|
||||
|
||||
## Testing the FlatBuffers Lua library
|
||||
|
||||
The code to test the Lua library can be found at `flatbuffers/tests`.
|
||||
The test code itself is located in [luatest.lua](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/luatest.lua).
|
||||
|
||||
To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/
|
||||
blob/master/tests/LuaTest.sh) shell script.
|
||||
|
||||
*Note: This script requires [Lua 5.3](https://www.lua.org/) to be
|
||||
installed.*
|
||||
|
||||
## Using the FlatBuffers Lua library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Lua.*
|
||||
|
||||
There is support for both reading and writing FlatBuffers in Lua.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Lua classes from your
|
||||
schema with the `--lua` option to `flatc`. Then you can include both
|
||||
FlatBuffers and the generated code to read or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Lua:
|
||||
First, require the module and the generated code. Then read a FlatBuffer binary
|
||||
file into a `string`, which you pass to the `GetRootAsMonster` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
||||
-- require the library
|
||||
local flatbuffers = require("flatbuffers")
|
||||
|
||||
-- require the generated code
|
||||
local monster = require("MyGame.Sample.Monster")
|
||||
|
||||
-- read the flatbuffer from a file into a string
|
||||
local f = io.open('monster.dat', 'rb')
|
||||
local buf = f:read('*a')
|
||||
f:close()
|
||||
|
||||
-- parse the flatbuffer to get an instance to the root monster
|
||||
local monster1 = monster.GetRootAsMonster(buf, 0)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
||||
-- use the : notation to access member data
|
||||
local hp = monster1:Hp()
|
||||
local pos = monster1:Pos()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
## Text Parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from Lua, though you could use the C++ parser through SWIG or ctypes. Please
|
||||
see the C++ documentation for more on text parsing.
|
||||
|
||||
<br>
|
||||
174
docs/source/RustUsage.md
Normal file
174
docs/source/RustUsage.md
Normal file
@@ -0,0 +1,174 @@
|
||||
Use in Rust {#flatbuffers_guide_use_rust}
|
||||
==========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Rust, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
||||
to general FlatBuffers usage in all of the supported languages (including Rust).
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Rust.
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
This page assumes you have written a FlatBuffers schema and compiled it
|
||||
with the Schema Compiler. If you have not, please see
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
|
||||
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
|
||||
matter), you've generated a Rust file called `mygame_generated.rs` using the
|
||||
compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful
|
||||
tools created by others" section bellow), you can now start using this in
|
||||
your program by including the file. As noted, this header relies on the crate
|
||||
`flatbuffers`, which should be in your include `Cargo.toml`.
|
||||
|
||||
## FlatBuffers Rust library code location
|
||||
|
||||
The code for the FlatBuffers Rust library can be found at
|
||||
`flatbuffers/rust`. You can browse the library code on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
|
||||
|
||||
## Testing the FlatBuffers Rust library
|
||||
|
||||
The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
|
||||
The test code itself is located in
|
||||
[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
|
||||
|
||||
This test file requires `flatc` to be present. To review how to build the project,
|
||||
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||
|
||||
To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
|
||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||
run: `cd tests && ./RustTest.sh`.
|
||||
|
||||
*Note: The shell script requires [Rust](https://www.rust-lang.org) to
|
||||
be installed.*
|
||||
|
||||
## Using the FlatBuffers Rust library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Rust.*
|
||||
|
||||
FlatBuffers supports both reading and writing FlatBuffers in Rust.
|
||||
|
||||
To use FlatBuffers in your code, first generate the Rust modules from your
|
||||
schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
|
||||
and the generated code to read or write FlatBuffers.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Rust:
|
||||
First, include the library and generated code. Then read the file into
|
||||
a `u8` vector, which you pass, as a byte slice, to `get_root_as_monster()`.
|
||||
|
||||
This full example program is available in the Rust test suite:
|
||||
[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
|
||||
|
||||
It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
||||
extern crate flatbuffers;
|
||||
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../monster_test_generated.rs"]
|
||||
mod monster_test_generated;
|
||||
pub use monster_test_generated::my_game;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
fn main() {
|
||||
let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
|
||||
let mut buf = Vec::new();
|
||||
f.read_to_end(&mut buf).expect("file reading failed");
|
||||
|
||||
let monster = my_game::example::get_root_as_monster(&buf[..]);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`monster` is of type `Monster`, and points to somewhere *inside* your
|
||||
buffer (root object pointers are not the same as `buffer_pointer` !).
|
||||
If you look in your generated header, you'll see it has
|
||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
||||
println!("{}", monster.hp()); // `80`
|
||||
println!("{}", monster.mana()); // default value of `150`
|
||||
println!("{:?}", monster.name()); // Some("MyMonster")
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||
|
||||
## Direct memory access
|
||||
|
||||
As you can see from the above examples, all elements in a buffer are
|
||||
accessed through generated accessors. This is because everything is
|
||||
stored in little endian format on all platforms (the accessor
|
||||
performs a swap operation on big endian machines), and also because
|
||||
the layout of things is generally not known to the user.
|
||||
|
||||
For structs, layout is deterministic and guaranteed to be the same
|
||||
across platforms (scalars are aligned to their
|
||||
own size, and structs themselves to their largest member), and you
|
||||
are allowed to access this memory directly by using `safe_slice` and
|
||||
on the reference to a struct, or even an array of structs.
|
||||
|
||||
To compute offsets to sub-elements of a struct, make sure they
|
||||
are structs themselves, as then you can use the pointers to
|
||||
figure out the offset without having to hardcode it. This is
|
||||
handy for use of arrays of structs with calls like `glVertexAttribPointer`
|
||||
in OpenGL or similar APIs.
|
||||
|
||||
It is important to note is that structs are still little endian on all
|
||||
machines, so only use tricks like this if you can guarantee you're not
|
||||
shipping on a big endian machine (using an `#[cfg(target_endian = "little")]`
|
||||
attribute would be wise).
|
||||
|
||||
The special function `safe_slice` is implemented on Vector objects that are
|
||||
represented in memory the same way as they are represented on the wire. This
|
||||
function is always available on vectors of struct, bool, u8, and i8. It is
|
||||
conditionally-compiled on little-endian systems for all the remaining scalar
|
||||
types.
|
||||
|
||||
The FlatBufferBuilder function `create_vector_direct` is implemented for all
|
||||
types that are endian-safe to write with a `memcpy`. It is the write-equivalent
|
||||
of `safe_slice`.
|
||||
|
||||
## Access of untrusted buffers
|
||||
|
||||
The generated accessor functions access fields over offsets, which is
|
||||
very quick. These offsets are used to index into Rust slices, so they are
|
||||
bounds-checked by the Rust runtime. However, our Rust implementation may
|
||||
change: we may convert access functions to use direct pointer dereferencing, to
|
||||
improve lookup speed. As a result, users should not rely on the aforementioned
|
||||
bounds-checking behavior.
|
||||
|
||||
When you're processing large amounts of data from a source you know (e.g.
|
||||
your own generated data on disk), this is acceptable, but when reading
|
||||
data from the network that can potentially have been modified by an
|
||||
attacker, this is undesirable.
|
||||
|
||||
The C++ port provides a buffer verifier. At this time, Rust does not. Rust may
|
||||
provide a verifier in a future version. In the meantime, Rust users can access
|
||||
the buffer verifier generated by the C++ port through a foreign function
|
||||
interface (FFI).
|
||||
|
||||
## Threading
|
||||
|
||||
Reading a FlatBuffer does not touch any memory outside the original buffer,
|
||||
and is entirely read-only (all immutable), so is safe to access from multiple
|
||||
threads even without synchronisation primitives.
|
||||
|
||||
Creating a FlatBuffer is not thread safe. All state related to building
|
||||
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
|
||||
outside of it is touched. To make this thread safe, either do not
|
||||
share instances of FlatBufferBuilder between threads (recommended), or
|
||||
manually wrap it in synchronisation primitives. There's no automatic way to
|
||||
accomplish this, by design, as we feel multithreaded construction
|
||||
of a single buffer will be rare, and synchronisation overhead would be costly.
|
||||
|
||||
## Useful tools created by others
|
||||
|
||||
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
|
||||
(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo
|
||||
build scripts integration.
|
||||
|
||||
<br>
|
||||
@@ -84,7 +84,7 @@ parent object, and use no virtual table).
|
||||
|
||||
### Types
|
||||
|
||||
Built-in scalar types are
|
||||
Built-in scalar types are
|
||||
|
||||
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
||||
|
||||
@@ -114,6 +114,27 @@ of same-size data where a `reinterpret_cast` would give you a desirable result,
|
||||
e.g. you could change a `uint` to an `int` if no values in current data use the
|
||||
high bit yet.
|
||||
|
||||
### Arrays
|
||||
|
||||
Arrays are a convenience short-hand for a fixed-length collection of elements.
|
||||
Arrays can be used to replace the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
x:float;
|
||||
y:float;
|
||||
z:float;
|
||||
}
|
||||
|
||||
with the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
v:[float:3];
|
||||
}
|
||||
|
||||
Both representations are binary equivalent.
|
||||
|
||||
Arrays are currently only supported in a `struct`.
|
||||
|
||||
### (Default) Values
|
||||
|
||||
Values are a sequence of digits. Values may be optionally followed by a decimal
|
||||
@@ -141,6 +162,9 @@ is `0`. As you can see in the enum declaration, you specify the underlying
|
||||
integral type of the enum with `:` (in this case `byte`), which then determines
|
||||
the type of any fields declared with this enum type.
|
||||
|
||||
Only integer types are allowed, i.e. `byte`, `ubyte`, `short` `ushort`, `int`,
|
||||
`uint`, `long` and `ulong`.
|
||||
|
||||
Typically, enum values should only ever be added, never removed (there is no
|
||||
deprecation for enums). This requires code to handle forwards compatibility
|
||||
itself, by handling unknown enum values.
|
||||
@@ -150,9 +174,23 @@ itself, by handling unknown enum values.
|
||||
Unions share a lot of properties with enums, but instead of new names
|
||||
for constants, you use names of tables. You can then declare
|
||||
a union field, which can hold a reference to any of those types, and
|
||||
additionally a hidden field with the suffix `_type` is generated that
|
||||
holds the corresponding enum value, allowing you to know which type to
|
||||
cast to at runtime.
|
||||
additionally a field with the suffix `_type` is generated that holds
|
||||
the corresponding enum value, allowing you to know which type to cast
|
||||
to at runtime.
|
||||
|
||||
It's possible to give an alias name to a type union. This way a type can even be
|
||||
used to mean different things depending on the name used:
|
||||
|
||||
table PointPosition { x:uint; y:uint; }
|
||||
table MarkerPosition {}
|
||||
union Position {
|
||||
Start:MarkerPosition,
|
||||
Point:PointPosition,
|
||||
Finish:MarkerPosition
|
||||
}
|
||||
|
||||
Unions contain a special `NONE` marker to denote that no value is stored so that
|
||||
name cannot be used as an alias.
|
||||
|
||||
Unions are a good way to be able to send multiple message types as a FlatBuffer.
|
||||
Note that because a union field is really two fields, it must always be
|
||||
@@ -304,8 +342,14 @@ Current understood attributes:
|
||||
these structs to be aligned to that amount inside a buffer, IF that
|
||||
buffer is allocated with that alignment (which is not necessarily
|
||||
the case for buffers accessed directly inside a `FlatBufferBuilder`).
|
||||
- `bit_flags` (on an enum): the values of this field indicate bits,
|
||||
meaning that any value N specified in the schema will end up
|
||||
Note: currently not guaranteed to have an effect when used with
|
||||
`--object-api`, since that may allocate objects at alignments less than
|
||||
what you specify with `force_align`.
|
||||
- `force_align: size` (on a vector): force the alignment of this vector to be
|
||||
something different than what the element size would normally dictate.
|
||||
Note: Now only work for generated C++ code.
|
||||
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
||||
meaning that any unsigned value N specified in the schema will end up
|
||||
representing 1<<N, or if you don't specify values at all, you'll get
|
||||
the sequence 1, 2, 4, 8, ...
|
||||
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
|
||||
@@ -385,6 +429,36 @@ When parsing JSON, it recognizes the following escape codes in strings:
|
||||
It also generates these escape codes back again when generating JSON from a
|
||||
binary representation.
|
||||
|
||||
When parsing numbers, the parser is more flexible than JSON.
|
||||
A format of numeric literals is more close to the C/C++.
|
||||
According to the [grammar](@ref flatbuffers_grammar), it accepts the following
|
||||
numerical literals:
|
||||
|
||||
- An integer literal can have any number of leading zero `0` digits.
|
||||
Unlike C/C++, the parser ignores a leading zero, not interpreting it as the
|
||||
beginning of the octal number.
|
||||
The numbers `[081, -00094]` are equal to `[81, -94]` decimal integers.
|
||||
- The parser accepts unsigned and signed hexadecimal integer numbers.
|
||||
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
|
||||
- The format of float-point numbers is fully compatible with C/C++ format.
|
||||
If a modern C++ compiler is used the parser accepts hexadecimal and special
|
||||
floating-point literals as well:
|
||||
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
|
||||
|
||||
The following conventions for floating-point numbers are used:
|
||||
- The exponent suffix of hexadecimal floating-point number is mandatory.
|
||||
- Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value.
|
||||
|
||||
Extended floating-point support was tested with:
|
||||
- x64 Windows: `MSVC2015` and higher.
|
||||
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
|
||||
|
||||
For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section.
|
||||
|
||||
- For compatibility with a JSON lint tool all numeric literals of scalar
|
||||
fields can be wrapped to quoted string:
|
||||
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
|
||||
|
||||
## Guidelines
|
||||
|
||||
### Efficiency
|
||||
@@ -492,7 +566,7 @@ with the new schema now cannot read nor write `a` anymore (any existing code
|
||||
that tries to do so will result in compile errors), but can still read
|
||||
old data (they will ignore the field).
|
||||
|
||||
table { c:int a:int; b:int; }
|
||||
table { c:int; a:int; b:int; }
|
||||
|
||||
This is NOT ok, as this makes the schemas incompatible. Old code reading newer
|
||||
data will interpret `c` as if it was `a`, and new code reading old data
|
||||
|
||||
@@ -18,28 +18,31 @@ In general:
|
||||
|
||||
NOTE: this table is a start, it needs to be extended.
|
||||
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ----
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ?
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ?
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ?
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ?
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ?
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ?
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ?
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ?
|
||||
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ------- | ------
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | ?
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
|
||||
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw | mi*/mz*
|
||||
|
||||
* aard = aardappel (previously: gwvo)
|
||||
* ev = evolutional
|
||||
* js = jonsimantov
|
||||
* mik = mikkelfj
|
||||
* ch = chobie
|
||||
* kr = krojew
|
||||
* mi = mustiikhalil
|
||||
* mz = mzaks
|
||||
|
||||
<br>
|
||||
|
||||
91
docs/source/SwiftUsage.md
Normal file
91
docs/source/SwiftUsage.md
Normal file
@@ -0,0 +1,91 @@
|
||||
Use in Swift {#flatbuffers_guide_use_swift}
|
||||
=========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Swift, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
||||
to general FlatBuffers usage in all of the supported languages (including Swift).
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Swift.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Swift library code location
|
||||
|
||||
The code for the FlatBuffers Swift library can be found at
|
||||
`flatbuffers/swift`. You can browse the library code on the [FlatBuffers
|
||||
GitHub page](https://github.com/google/flatbuffers/tree/master/swift).
|
||||
|
||||
## Testing the FlatBuffers Swift library
|
||||
|
||||
The code to test the Swift library can be found at `flatbuffers/Flatbuffers.Test.Swift`.
|
||||
The test code itself is located in [Flatbuffers.Test.Swift](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift).
|
||||
|
||||
To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift/SwiftTest.sh) shell script.
|
||||
|
||||
*Note: The shell script requires [Swift](https://swift.org) to
|
||||
be installed.*
|
||||
|
||||
## Using the FlatBuffers Swift library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Swift.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Swift.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Swift structs from your
|
||||
schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in
|
||||
by adding the path to `FlatBuffers/swift` into it. The generated code should also be
|
||||
added to xcode or the path of the package you will be using. Note: sometimes xcode cant
|
||||
and wont see the generated files, so it's better that you copy them to xcode.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Swift: First,
|
||||
include the library and copy thegenerated code. Then read a FlatBuffer binary file or
|
||||
a data object from the server, which you can pass into the `GetRootAsMonster` function.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
import FlatBuffers
|
||||
|
||||
typealias Monster1 = MyGame.Sample.Monster
|
||||
typealias Vec3 = MyGame.Sample.Vec3
|
||||
|
||||
let path = FileManager.default.currentDirectoryPath
|
||||
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
|
||||
guard let data = try? Data(contentsOf: url) else { return }
|
||||
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let hp = monster.hp
|
||||
let pos = monster.pos
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
|
||||
if !monster.mutate(hp: 10) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
// mutate a struct field
|
||||
let vec = monster.pos.mutate(z: 4)
|
||||
|
||||
// This mutation will fail because the mana field is not available in
|
||||
// the buffer. It should be set when creating the buffer.
|
||||
if !monster.mutate(mana: 20) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
|
||||
|
||||
<br>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@ documentation to build `flatc` and should be familiar with
|
||||
## FlatBuffers TypeScript library code location
|
||||
|
||||
The code for the FlatBuffers TypeScript library can be found at
|
||||
`flatbuffers/js` with typings available at @types/flatubffers.
|
||||
`flatbuffers/js` with typings available at `@types/flatbuffers`.
|
||||
|
||||
## Testing the FlatBuffers TypeScript library
|
||||
|
||||
@@ -43,7 +43,7 @@ First, include the library and generated code. Then read the file into an
|
||||
the ByteBuffer to the `getRootAsMonster` function.
|
||||
|
||||
~~~{.ts}
|
||||
// note: import flabuffers with your desired import method
|
||||
// note: import flatbuffers with your desired import method
|
||||
|
||||
import { MyGame } from './monster_generated';
|
||||
|
||||
|
||||
@@ -751,11 +751,16 @@ INPUT = "FlatBuffers.md" \
|
||||
"Schemas.md" \
|
||||
"CppUsage.md" \
|
||||
"CUsage.md" \
|
||||
"DartUsage.md" \
|
||||
"GoUsage.md" \
|
||||
"JavaCsharpUsage.md" \
|
||||
"JavaScriptUsage.md" \
|
||||
"TypeScriptUsage.md" \
|
||||
"PHPUsage.md" \
|
||||
"PythonUsage.md" \
|
||||
"LuaUsage.md" \
|
||||
"LobsterUsage.md" \
|
||||
"RustUsage.md" \
|
||||
"Support.md" \
|
||||
"Benchmarks.md" \
|
||||
"WhitePaper.md" \
|
||||
@@ -773,7 +778,8 @@ INPUT = "FlatBuffers.md" \
|
||||
"../../php/FlatbufferBuilder.php" \
|
||||
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
|
||||
"../../include/flatbuffers/flatbuffers.h" \
|
||||
"../../go/builder.go"
|
||||
"../../go/builder.go" \
|
||||
"../../rust/flatbuffers/src/builder.rs"
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
title="Use in C"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_go"
|
||||
title="Use in Go"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java_c-sharp"
|
||||
title="Use in Java/C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java"
|
||||
title="Use in Java"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_c-sharp"
|
||||
title="Use in C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
||||
title="Use in JavaScript"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
|
||||
@@ -39,8 +41,16 @@
|
||||
title="Use in PHP"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_python"
|
||||
title="Use in Python"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_dart"
|
||||
title="Use in Dart"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_lua"
|
||||
title="Use in Lua"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_lobster"
|
||||
title="Use in Lobster"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_rust"
|
||||
title="Use in Rust"/>
|
||||
<tab type="user" url="@ref flexbuffers"
|
||||
title="Schema-less version"/>
|
||||
title="FlexBuffers (Schema-less version)"/>
|
||||
<tab type="usergroup" url="" title="gRPC">
|
||||
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
|
||||
title="Use in C++"/>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":go",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go",
|
||||
srcs = [
|
||||
|
||||
@@ -17,8 +17,12 @@ type Builder struct {
|
||||
head UOffsetT
|
||||
nested bool
|
||||
finished bool
|
||||
|
||||
sharedStrings map[string]UOffsetT
|
||||
}
|
||||
|
||||
const fileIdentifierLength = 4
|
||||
|
||||
// NewBuilder initializes a Builder of size `initial_size`.
|
||||
// The internal buffer is grown as needed.
|
||||
func NewBuilder(initialSize int) *Builder {
|
||||
@@ -31,7 +35,6 @@ func NewBuilder(initialSize int) *Builder {
|
||||
b.head = UOffsetT(initialSize)
|
||||
b.minalign = 1
|
||||
b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -80,7 +83,6 @@ func (b *Builder) StartObject(numfields int) {
|
||||
}
|
||||
|
||||
b.objectEnd = b.Offset()
|
||||
b.minalign = 1
|
||||
}
|
||||
|
||||
// WriteVtable serializes the vtable for the current object, if applicable.
|
||||
@@ -111,9 +113,10 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
|
||||
existingVtable := UOffsetT(0)
|
||||
|
||||
// Trim vtable of trailing zeroes.
|
||||
i := len(b.vtable) - 1;
|
||||
for ; i >= 0 && b.vtable[i] == 0; i-- {}
|
||||
b.vtable = b.vtable[:i + 1];
|
||||
i := len(b.vtable) - 1
|
||||
for ; i >= 0 && b.vtable[i] == 0; i-- {
|
||||
}
|
||||
b.vtable = b.vtable[:i+1]
|
||||
|
||||
// Search backwards through existing vtables, because similar vtables
|
||||
// are likely to have been recently appended. See
|
||||
@@ -305,6 +308,20 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
|
||||
return b.Offset()
|
||||
}
|
||||
|
||||
// CreateSharedString Checks if the string is already written
|
||||
// to the buffer before calling CreateString
|
||||
func (b *Builder) CreateSharedString(s string) UOffsetT {
|
||||
if b.sharedStrings == nil {
|
||||
b.sharedStrings = make(map[string]UOffsetT)
|
||||
}
|
||||
if v, ok := b.sharedStrings[s]; ok {
|
||||
return v
|
||||
}
|
||||
off := b.CreateString(s)
|
||||
b.sharedStrings[s] = off
|
||||
return off
|
||||
}
|
||||
|
||||
// CreateString writes a null-terminated string as a vector.
|
||||
func (b *Builder) CreateString(s string) UOffsetT {
|
||||
b.assertNotNested()
|
||||
@@ -540,6 +557,23 @@ func (b *Builder) Slot(slotnum int) {
|
||||
b.vtable[slotnum] = UOffsetT(b.Offset())
|
||||
}
|
||||
|
||||
// FinishWithFileIdentifier finalizes a buffer, pointing to the given `rootTable`.
|
||||
// as well as applys a file identifier
|
||||
func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fid []byte) {
|
||||
if fid == nil || len(fid) != fileIdentifierLength {
|
||||
panic("incorrect file identifier length")
|
||||
}
|
||||
// In order to add a file identifier to the flatbuffer message, we need
|
||||
// to prepare an alignment and file identifier length
|
||||
b.Prep(b.minalign, SizeInt32+fileIdentifierLength)
|
||||
for i := fileIdentifierLength - 1; i >= 0; i-- {
|
||||
// place the file identifier
|
||||
b.PlaceByte(fid[i])
|
||||
}
|
||||
// finish
|
||||
b.Finish(rootTable)
|
||||
}
|
||||
|
||||
// Finish finalizes a buffer, pointing to the given `rootTable`.
|
||||
func (b *Builder) Finish(rootTable UOffsetT) {
|
||||
b.assertNotNested()
|
||||
|
||||
34
go/encode.go
34
go/encode.go
@@ -36,6 +36,7 @@ func GetUint8(buf []byte) (n uint8) {
|
||||
|
||||
// GetUint16 decodes a little-endian uint16 from a byte slice.
|
||||
func GetUint16(buf []byte) (n uint16) {
|
||||
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= uint16(buf[0])
|
||||
n |= uint16(buf[1]) << 8
|
||||
return
|
||||
@@ -43,6 +44,7 @@ func GetUint16(buf []byte) (n uint16) {
|
||||
|
||||
// GetUint32 decodes a little-endian uint32 from a byte slice.
|
||||
func GetUint32(buf []byte) (n uint32) {
|
||||
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= uint32(buf[0])
|
||||
n |= uint32(buf[1]) << 8
|
||||
n |= uint32(buf[2]) << 16
|
||||
@@ -52,6 +54,7 @@ func GetUint32(buf []byte) (n uint32) {
|
||||
|
||||
// GetUint64 decodes a little-endian uint64 from a byte slice.
|
||||
func GetUint64(buf []byte) (n uint64) {
|
||||
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= uint64(buf[0])
|
||||
n |= uint64(buf[1]) << 8
|
||||
n |= uint64(buf[2]) << 16
|
||||
@@ -71,6 +74,7 @@ func GetInt8(buf []byte) (n int8) {
|
||||
|
||||
// GetInt16 decodes a little-endian int16 from a byte slice.
|
||||
func GetInt16(buf []byte) (n int16) {
|
||||
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= int16(buf[0])
|
||||
n |= int16(buf[1]) << 8
|
||||
return
|
||||
@@ -78,6 +82,7 @@ func GetInt16(buf []byte) (n int16) {
|
||||
|
||||
// GetInt32 decodes a little-endian int32 from a byte slice.
|
||||
func GetInt32(buf []byte) (n int32) {
|
||||
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= int32(buf[0])
|
||||
n |= int32(buf[1]) << 8
|
||||
n |= int32(buf[2]) << 16
|
||||
@@ -87,6 +92,7 @@ func GetInt32(buf []byte) (n int32) {
|
||||
|
||||
// GetInt64 decodes a little-endian int64 from a byte slice.
|
||||
func GetInt64(buf []byte) (n int64) {
|
||||
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||
n |= int64(buf[0])
|
||||
n |= int64(buf[1]) << 8
|
||||
n |= int64(buf[2]) << 16
|
||||
@@ -145,12 +151,14 @@ func WriteUint8(buf []byte, n uint8) {
|
||||
|
||||
// WriteUint16 encodes a little-endian uint16 into a byte slice.
|
||||
func WriteUint16(buf []byte, n uint16) {
|
||||
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
}
|
||||
|
||||
// WriteUint32 encodes a little-endian uint32 into a byte slice.
|
||||
func WriteUint32(buf []byte, n uint32) {
|
||||
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
buf[2] = byte(n >> 16)
|
||||
@@ -159,9 +167,15 @@ func WriteUint32(buf []byte, n uint32) {
|
||||
|
||||
// WriteUint64 encodes a little-endian uint64 into a byte slice.
|
||||
func WriteUint64(buf []byte, n uint64) {
|
||||
for i := uint(0); i < uint(SizeUint64); i++ {
|
||||
buf[i] = byte(n >> (i * 8))
|
||||
}
|
||||
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
buf[2] = byte(n >> 16)
|
||||
buf[3] = byte(n >> 24)
|
||||
buf[4] = byte(n >> 32)
|
||||
buf[5] = byte(n >> 40)
|
||||
buf[6] = byte(n >> 48)
|
||||
buf[7] = byte(n >> 56)
|
||||
}
|
||||
|
||||
// WriteInt8 encodes a little-endian int8 into a byte slice.
|
||||
@@ -171,12 +185,14 @@ func WriteInt8(buf []byte, n int8) {
|
||||
|
||||
// WriteInt16 encodes a little-endian int16 into a byte slice.
|
||||
func WriteInt16(buf []byte, n int16) {
|
||||
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
}
|
||||
|
||||
// WriteInt32 encodes a little-endian int32 into a byte slice.
|
||||
func WriteInt32(buf []byte, n int32) {
|
||||
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
buf[2] = byte(n >> 16)
|
||||
@@ -185,9 +201,15 @@ func WriteInt32(buf []byte, n int32) {
|
||||
|
||||
// WriteInt64 encodes a little-endian int64 into a byte slice.
|
||||
func WriteInt64(buf []byte, n int64) {
|
||||
for i := uint(0); i < uint(SizeInt64); i++ {
|
||||
buf[i] = byte(n >> (i * 8))
|
||||
}
|
||||
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||
buf[0] = byte(n)
|
||||
buf[1] = byte(n >> 8)
|
||||
buf[2] = byte(n >> 16)
|
||||
buf[3] = byte(n >> 24)
|
||||
buf[4] = byte(n >> 32)
|
||||
buf[5] = byte(n >> 40)
|
||||
buf[6] = byte(n >> 48)
|
||||
buf[7] = byte(n >> 56)
|
||||
}
|
||||
|
||||
// WriteFloat32 encodes a little-endian float32 into a byte slice.
|
||||
|
||||
15
go/grpc.go
15
go/grpc.go
@@ -3,21 +3,36 @@ package flatbuffers
|
||||
// Codec implements gRPC-go Codec which is used to encode and decode messages.
|
||||
var Codec = "flatbuffers"
|
||||
|
||||
// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
|
||||
// that implementations of this interface must be thread safe; a Codec's
|
||||
// methods can be called from concurrent goroutines.
|
||||
type FlatbuffersCodec struct{}
|
||||
|
||||
// Marshal returns the wire format of v.
|
||||
func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
|
||||
return v.(*Builder).FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire format into v.
|
||||
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
// String old gRPC Codec interface func
|
||||
func (FlatbuffersCodec) String() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
//
|
||||
// add Name() for ForceCodec interface
|
||||
func (FlatbuffersCodec) Name() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
type flatbuffersInit interface {
|
||||
Init(data []byte, i UOffsetT)
|
||||
}
|
||||
|
||||
@@ -9,3 +9,23 @@ from GRPC, and work with both the Protobuf and FlatBuffers code generator.
|
||||
the GRPC libraries for this to compile. This test will build using the
|
||||
`FLATBUFFERS_BUILD_GRPCTEST` option to the main FlatBuffers CMake project.
|
||||
|
||||
## Building Flatbuffers with gRPC
|
||||
|
||||
### Linux
|
||||
|
||||
1. Download, build and install gRPC. See [instructions](https://github.com/grpc/grpc/tree/master/src/cpp).
|
||||
* Lets say your gRPC clone is at `/your/path/to/grpc_repo`.
|
||||
* Install gRPC in a custom directory by running `make install prefix=/your/path/to/grpc_repo/install`.
|
||||
2. `export GRPC_INSTALL_PATH=/your/path/to/grpc_repo/install`
|
||||
3. `export PROTOBUF_DOWNLOAD_PATH=/your/path/to/grpc_repo/third_party/protobuf`
|
||||
4. `mkdir build ; cd build`
|
||||
5. `cmake -DFLATBUFFERS_BUILD_GRPCTEST=ON -DGRPC_INSTALL_PATH=${GRPC_INSTALL_PATH} -DPROTOBUF_DOWNLOAD_PATH=${PROTOBUF_DOWNLOAD_PATH} ..`
|
||||
6. `make`
|
||||
|
||||
## Running FlatBuffer gRPC tests
|
||||
|
||||
### Linux
|
||||
|
||||
1. `ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1`
|
||||
2. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
|
||||
3. `make test ARGS=-V`
|
||||
|
||||
21
grpc/build_grpc.sh
Executable file
21
grpc/build_grpc.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
grpc_1_15_1_githash=1a60e6971f428323245a930031ad267bb3142ba4
|
||||
|
||||
function build_grpc () {
|
||||
git clone https://github.com/grpc/grpc.git google/grpc
|
||||
cd google/grpc
|
||||
git checkout ${grpc_1_15_1_githash}
|
||||
git submodule update --init
|
||||
make
|
||||
make install prefix=`pwd`/install
|
||||
if [ ! -f ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1 ]; then
|
||||
ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1
|
||||
fi
|
||||
cd ../..
|
||||
}
|
||||
|
||||
GRPC_INSTALL_PATH=`pwd`/google/grpc/install
|
||||
PROTOBUF_DOWNLOAD_PATH=`pwd`/google/grpc/third_party/protobuf
|
||||
|
||||
build_grpc
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>1.8.0</version>
|
||||
<version>1.12.0</version>
|
||||
</parent>
|
||||
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
@@ -24,7 +24,7 @@
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<gRPC.version>1.8.0</gRPC.version>
|
||||
<gRPC.version>1.12.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
10
grpc/pom.xml
10
grpc/pom.xml
@@ -4,7 +4,7 @@
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.8.0</version>
|
||||
<version>1.12.0</version>
|
||||
<name>flatbuffers-parent</name>
|
||||
<description>parent pom for flatbuffers java artifacts</description>
|
||||
<properties>
|
||||
@@ -185,6 +185,12 @@
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<gpgArguments>
|
||||
<arg>--pinentry-mode</arg>
|
||||
<arg>loopback</arg>
|
||||
</gpgArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
@@ -201,7 +207,7 @@
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
<!-- consider the benefits of publishing all maven artifacts in this project
|
||||
<!-- consider the benefits of publishing all maven artifacts in this project
|
||||
|
||||
<module>flatbuffers-compiler</module>
|
||||
<module>flatbuffers-java</module>
|
||||
|
||||
@@ -12,7 +12,8 @@ class GreeterServiceImpl final : public Greeter::Service {
|
||||
grpc::ServerContext *context,
|
||||
const flatbuffers::grpc::Message<HelloRequest> *request_msg,
|
||||
flatbuffers::grpc::Message<HelloReply> *response_msg) override {
|
||||
// flatbuffers::grpc::MessageBuilder mb_;
|
||||
flatbuffers::grpc::MessageBuilder mb_;
|
||||
|
||||
// We call GetRoot to "parse" the message. Verification is already
|
||||
// performed by default. See the notes below for more details.
|
||||
const HelloRequest *request = request_msg->GetRoot();
|
||||
|
||||
107
grpc/src/compiler/BUILD
Normal file
107
grpc/src/compiler/BUILD
Normal file
@@ -0,0 +1,107 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "common_headers",
|
||||
srcs = [
|
||||
"config.h",
|
||||
"schema_interface.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "cpp_generator",
|
||||
srcs = [
|
||||
"cpp_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"cpp_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "go_generator",
|
||||
srcs = [
|
||||
"go_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"go_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "java_generator",
|
||||
srcs = [
|
||||
"java_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"java_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator",
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
":python_generator_private",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator_private",
|
||||
srcs = [
|
||||
"python_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
"python_private_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "swift_generator",
|
||||
srcs = [
|
||||
"swift_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"swift_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
@@ -84,7 +84,7 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
|
||||
}
|
||||
printer->Print("import (\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "$context$ \"golang.org/x/net/context\"\n");
|
||||
printer->Print(vars, "$context$ \"context\"\n");
|
||||
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
|
||||
printer->Outdent();
|
||||
printer->Print(")\n\n");
|
||||
@@ -110,7 +110,7 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = method->get_input_type_name();
|
||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
|
||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
|
||||
if (method->NoStreaming()) {
|
||||
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
|
||||
@@ -223,7 +223,7 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
|
||||
vars["Response"] = method->get_output_type_name();
|
||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
if (method->NoStreaming()) {
|
||||
printer->Print(vars, "out := new($Response$)\n");
|
||||
printer->Print(vars, "err := $grpc$.Invoke(ctx, \"$FullMethodName$\", in, out, c.cc, opts...)\n");
|
||||
@@ -374,7 +374,7 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
|
||||
//Service Descriptor
|
||||
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "ServiceName: \"$Package$.$Service$\",\n");
|
||||
printer->Print(vars, "ServiceName: \"$ServicePrefix$.$Service$\",\n");
|
||||
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
|
||||
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
|
||||
printer->Indent();
|
||||
@@ -433,6 +433,7 @@ grpc::string GenerateServiceSource(grpc_generator::File *file,
|
||||
auto printer = p.get();
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
vars["Package"] = parameters->package_name;
|
||||
vars["ServicePrefix"] = parameters->service_prefix;
|
||||
vars["grpc"] = "grpc";
|
||||
vars["context"] = "context";
|
||||
GenerateImports(file, printer, vars);
|
||||
|
||||
@@ -49,6 +49,9 @@ struct Parameters {
|
||||
|
||||
//Package name for the service
|
||||
grpc::string package_name;
|
||||
|
||||
//Prefix for RPC Calls
|
||||
grpc::string service_prefix;
|
||||
};
|
||||
|
||||
// Return the source of the generated service file.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "java_generator.h"
|
||||
#include "src/compiler/java_generator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -37,9 +37,6 @@
|
||||
#define XSTR(s) STR(s)
|
||||
#endif
|
||||
|
||||
#ifndef FALLTHROUGH_INTENDED
|
||||
#define FALLTHROUGH_INTENDED
|
||||
#endif
|
||||
|
||||
typedef grpc_generator::Printer Printer;
|
||||
typedef std::map<grpc::string, grpc::string> VARS;
|
||||
@@ -72,13 +69,14 @@ void GenerateImports(grpc_generator::File* file,
|
||||
// - remove embedded underscores & capitalize the following letter
|
||||
static string MixedLower(const string& word) {
|
||||
string w;
|
||||
w += (string::value_type)tolower(word[0]);
|
||||
w += static_cast<string::value_type>(tolower(word[0]));
|
||||
bool after_underscore = false;
|
||||
for (size_t i = 1; i < word.length(); ++i) {
|
||||
if (word[i] == '_') {
|
||||
after_underscore = true;
|
||||
} else {
|
||||
w += after_underscore ? (string::value_type)toupper(word[i]) : word[i];
|
||||
w += after_underscore ? static_cast<string::value_type>(toupper(word[i]))
|
||||
: word[i];
|
||||
after_underscore = false;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +90,7 @@ static string MixedLower(const string& word) {
|
||||
static string ToAllUpperCase(const string& word) {
|
||||
string w;
|
||||
for (size_t i = 0; i < word.length(); ++i) {
|
||||
w += (string::value_type)toupper(word[i]);
|
||||
w += static_cast<string::value_type>(toupper(word[i]));
|
||||
if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
|
||||
w += '_';
|
||||
}
|
||||
@@ -345,8 +343,8 @@ static void PrintMethodFields(Printer* p, VARS& vars,
|
||||
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
vars["arg_in_id"] = to_string((long)2 * i); //trying to make msvc 10 happy
|
||||
vars["arg_out_id"] = to_string((long)2 * i + 1);
|
||||
vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy
|
||||
vars["arg_out_id"] = to_string(2L * i + 1);
|
||||
vars["method_name"] = method->name();
|
||||
vars["input_type_name"] = method->get_input_type_name();
|
||||
vars["output_type_name"] = method->get_output_type_name();
|
||||
@@ -355,8 +353,8 @@ static void PrintMethodFields(Printer* p, VARS& vars,
|
||||
vars["method_field_name"] = MethodPropertiesFieldName(method.get());
|
||||
vars["method_new_field_name"] = MethodPropertiesGetterName(method.get());
|
||||
vars["method_method_name"] = MethodPropertiesGetterName(method.get());
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
if (client_streaming) {
|
||||
if (server_streaming) {
|
||||
vars["method_type"] = "BIDI_STREAMING";
|
||||
@@ -478,7 +476,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
||||
break;
|
||||
case BLOCKING_CLIENT_INTERFACE:
|
||||
interface = true;
|
||||
FALLTHROUGH_INTENDED; // fallthrough
|
||||
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BLOCKING_CLIENT_IMPL:
|
||||
call_type = BLOCKING_CALL;
|
||||
stub_name += "BlockingStub";
|
||||
@@ -486,7 +484,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
||||
break;
|
||||
case FUTURE_CLIENT_INTERFACE:
|
||||
interface = true;
|
||||
FALLTHROUGH_INTENDED; // fallthrough
|
||||
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case FUTURE_CLIENT_IMPL:
|
||||
call_type = FUTURE_CALL;
|
||||
stub_name += "FutureStub";
|
||||
@@ -548,8 +546,8 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
||||
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
||||
vars["lower_method_name"] = LowerMethodName(&*method);
|
||||
vars["method_method_name"] = MethodPropertiesGetterName(&*method);
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
|
||||
if (call_type == BLOCKING_CALL && client_streaming) {
|
||||
// Blocking client interface with client streaming is not available
|
||||
@@ -759,7 +757,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
|
||||
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
if (method->ClientStreaming()) {
|
||||
if (method->ClientStreaming() || method->BidiStreaming()) {
|
||||
continue;
|
||||
}
|
||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||
@@ -793,7 +791,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
|
||||
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
if (!method->ClientStreaming()) {
|
||||
if (!(method->ClientStreaming() || method->BidiStreaming())) {
|
||||
continue;
|
||||
}
|
||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||
@@ -929,8 +927,8 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
|
||||
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
|
||||
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
if (client_streaming) {
|
||||
if (server_streaming) {
|
||||
vars["calls_method"] = "asyncBidiStreamingCall";
|
||||
|
||||
@@ -65,8 +65,6 @@ class LogHelper {
|
||||
// Abort the program after logging the mesage.
|
||||
#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace grpc_java_generator {
|
||||
struct Parameters {
|
||||
// //Defines the custom parameter types for methods
|
||||
|
||||
624
grpc/src/compiler/python_generator.cc
Normal file
624
grpc/src/compiler/python_generator.cc
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/python_private_generator.h"
|
||||
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::replace;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
grpc::string generator_file_name;
|
||||
|
||||
typedef map<grpc::string, grpc::string> StringMap;
|
||||
typedef vector<grpc::string> StringVector;
|
||||
typedef tuple<grpc::string, grpc::string> StringPair;
|
||||
typedef set<StringPair> StringPairSet;
|
||||
|
||||
// Provides RAII indentation handling. Use as:
|
||||
// {
|
||||
// IndentScope raii_my_indent_var_name_here(my_py_printer);
|
||||
// // constructor indented my_py_printer
|
||||
// ...
|
||||
// // destructor called at end of scope, un-indenting my_py_printer
|
||||
// }
|
||||
class IndentScope {
|
||||
public:
|
||||
explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) {
|
||||
printer_->Indent();
|
||||
}
|
||||
|
||||
~IndentScope() { printer_->Outdent(); }
|
||||
|
||||
private:
|
||||
grpc_generator::Printer* printer_;
|
||||
};
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to, bool replace_all) {
|
||||
size_t pos = 0;
|
||||
|
||||
do {
|
||||
pos = str.find(from, pos);
|
||||
if (pos == grpc::string::npos) {
|
||||
break;
|
||||
}
|
||||
str.replace(pos, from.length(), to);
|
||||
pos += to.length();
|
||||
} while (replace_all);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to) {
|
||||
return StringReplace(str, from, to, true);
|
||||
}
|
||||
|
||||
grpc::string ModuleName(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string basename = flatbuffers::StripExtension(filename);
|
||||
basename = StringReplace(basename, "-", "_");
|
||||
basename = StringReplace(basename, "/", ".");
|
||||
return import_prefix + basename + "_fb";
|
||||
}
|
||||
|
||||
grpc::string ModuleAlias(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string module_name = ModuleName(filename, import_prefix);
|
||||
// We can't have dots in the module name, so we replace each with _dot_.
|
||||
// But that could lead to a collision between a.b and a_dot_b, so we also
|
||||
// duplicate each underscore.
|
||||
module_name = StringReplace(module_name, "_", "__");
|
||||
module_name = StringReplace(module_name, ".", "_dot_");
|
||||
return module_name;
|
||||
}
|
||||
|
||||
PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config_,
|
||||
const grpc_generator::File* file_)
|
||||
: config(config_), file(file_) {}
|
||||
|
||||
void PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict,
|
||||
"def $Method$(self, $ArgName$, timeout, metadata=None, "
|
||||
"with_call=False, protocol_options=None):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("raise NotImplementedError()\n");
|
||||
}
|
||||
if (!method->ServerStreaming()) {
|
||||
out->Print(method_dict, "$Method$.future = None\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def beta_create_$Service$_server(servicer, pool=None, "
|
||||
"pool_size=None, default_timeout=None, maximum_timeout=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_implementation_constructors;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_implementation_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream_" : "unary_") +
|
||||
grpc::string(method->ServerStreaming() ? "stream_" : "unary_") +
|
||||
"inline";
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_implementation_constructors.insert(
|
||||
make_pair(method->name(), method_implementation_constructor));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("method_implementations = {\n");
|
||||
for (StringMap::iterator name_and_implementation_constructor =
|
||||
method_implementation_constructors.begin();
|
||||
name_and_implementation_constructor !=
|
||||
method_implementation_constructors.end();
|
||||
name_and_implementation_constructor++) {
|
||||
method_dict["Method"] = name_and_implementation_constructor->first;
|
||||
method_dict["Constructor"] = name_and_implementation_constructor->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
const grpc::string method_name =
|
||||
name_and_implementation_constructor->first;
|
||||
out->Print(method_dict,
|
||||
"(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
|
||||
"face_utilities.$Constructor$(servicer.$Method$),\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"server_options = beta_implementations.server_options("
|
||||
"thread_pool=pool, thread_pool_size=pool_size, "
|
||||
"default_timeout=default_timeout, "
|
||||
"maximum_timeout=maximum_timeout)\n");
|
||||
out->Print(
|
||||
"return beta_implementations.server(method_implementations, "
|
||||
"options=server_options)\n");
|
||||
//"request_deserializers=request_deserializers, "
|
||||
//"response_serializers=response_serializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStubFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict,
|
||||
"def beta_create_$Service$_stub(channel, host=None,"
|
||||
" metadata_transformer=None, pool=None, pool_size=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_cardinalities;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_cardinality =
|
||||
grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY");
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_cardinalities.insert(
|
||||
make_pair(method->name(), method_cardinality));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("cardinalities = {\n");
|
||||
for (StringMap::iterator name_and_cardinality =
|
||||
method_cardinalities.begin();
|
||||
name_and_cardinality != method_cardinalities.end();
|
||||
name_and_cardinality++) {
|
||||
method_dict["Method"] = name_and_cardinality->first;
|
||||
method_dict["Cardinality"] = name_and_cardinality->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
out->Print(method_dict,
|
||||
"\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"stub_options = beta_implementations.stub_options("
|
||||
"host=host, metadata_transformer=metadata_transformer, "
|
||||
"thread_pool=pool, thread_pool_size=pool_size)\n");
|
||||
out->Print(method_dict,
|
||||
"return beta_implementations.dynamic_stub(channel, "
|
||||
"\'$PackageQualifiedServiceName$\', "
|
||||
"cardinalities, options=stub_options)\n");
|
||||
// "request_serializers=request_serializers, "
|
||||
//"response_deserializers=response_deserializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintStub(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict, "class $Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("\n");
|
||||
out->Print("def __init__(self, channel):\n");
|
||||
{
|
||||
IndentScope raii_init_indent(out);
|
||||
out->Print("\"\"\"Constructor.\n");
|
||||
out->Print("\n");
|
||||
out->Print("Args:\n");
|
||||
{
|
||||
IndentScope raii_args_indent(out);
|
||||
out->Print("channel: A grpc.Channel.\n");
|
||||
}
|
||||
out->Print("\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string multi_callable_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary");
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MultiCallableConstructor"] = multi_callable_constructor;
|
||||
out->Print(method_dict,
|
||||
"self.$Method$ = channel.$MultiCallableConstructor$(\n");
|
||||
{
|
||||
method_dict["PackageQualifiedService"] =
|
||||
package_qualified_service_name;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
IndentScope raii_first_attribute_indent(out);
|
||||
IndentScope raii_second_attribute_indent(out);
|
||||
out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n");
|
||||
out->Print(method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class $Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print("\n");
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
|
||||
out->Print("context.set_details('Method not implemented!')\n");
|
||||
out->Print("raise NotImplementedError('Method not implemented!')\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def add_$Service$Servicer_to_server(servicer, server):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("rpc_method_handlers = {\n");
|
||||
{
|
||||
IndentScope raii_dict_first_indent(out);
|
||||
IndentScope raii_dict_second_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string method_handler_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary") +
|
||||
"_rpc_method_handler";
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MethodHandlerConstructor"] = method_handler_constructor;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
out->Print(method_dict,
|
||||
"'$Method$': grpc.$MethodHandlerConstructor$(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict, "servicer.$Method$,\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,
|
||||
"\n");
|
||||
}
|
||||
out->Print("),\n");
|
||||
}
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
out->Print("}\n");
|
||||
out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict,
|
||||
"'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
|
||||
}
|
||||
out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.beta_package_root;
|
||||
out->Print(var,
|
||||
"from $Package$ import implementations as beta_implementations\n");
|
||||
out->Print(var, "from $Package$ import interfaces as beta_interfaces\n");
|
||||
out->Print("from grpc.framework.common import cardinality\n");
|
||||
out->Print(
|
||||
"from grpc.framework.interfaces.face import utilities as "
|
||||
"face_utilities\n");
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
out->Print("\n");
|
||||
StringPairSet imports_set;
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
for (int j = 0; j < service->method_count(); ++j) {
|
||||
auto method = service.get()->method(j);
|
||||
|
||||
grpc::string input_type_file_name = method->get_fb_builder();
|
||||
grpc::string input_module_name =
|
||||
ModuleName(input_type_file_name, config.import_prefix);
|
||||
grpc::string input_module_alias =
|
||||
ModuleAlias(input_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(input_module_name, input_module_alias));
|
||||
|
||||
grpc::string output_type_file_name = method->get_fb_builder();
|
||||
grpc::string output_module_name =
|
||||
ModuleName(output_type_file_name, config.import_prefix);
|
||||
grpc::string output_module_alias =
|
||||
ModuleAlias(output_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(output_module_name, output_module_alias));
|
||||
}
|
||||
}
|
||||
|
||||
for (StringPairSet::iterator it = imports_set.begin();
|
||||
it != imports_set.end(); ++it) {
|
||||
var["ModuleName"] = std::get<0>(*it);
|
||||
var["ModuleAlias"] = std::get<1>(*it);
|
||||
out->Print(var, "import $ModuleName$ as $ModuleAlias$\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
|
||||
out->Print(file->additional_headers().c_str());
|
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintStub(package_qualified_service_name, service.get(), out);
|
||||
PrintServicer(service.get(), out);
|
||||
PrintAddServicerToServer(package_qualified_service_name, service.get(),
|
||||
out);
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintBetaServicer(service.get(), out);
|
||||
PrintBetaStub(service.get(), out);
|
||||
PrintBetaServerFactory(package_qualified_service_name, service.get(), out);
|
||||
PrintBetaStubFactory(package_qualified_service_name, service.get(), out);
|
||||
}
|
||||
}
|
||||
|
||||
grpc::string PrivateGenerator::GetGrpcServices() {
|
||||
grpc::string output;
|
||||
{
|
||||
// Scope the output stream so it closes and finalizes output to the string.
|
||||
auto out = file->CreatePrinter(&output);
|
||||
out->Print(
|
||||
"# Generated by the gRPC Python protocol compiler plugin. "
|
||||
"DO NOT EDIT!\n");
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintGAServices(out.get());
|
||||
out->Print("try:\n");
|
||||
{
|
||||
IndentScope raii_dict_try_indent(out.get());
|
||||
out->Print(
|
||||
"# THESE ELEMENTS WILL BE DEPRECATED.\n"
|
||||
"# Please use the generated *_pb2_grpc.py files instead.\n");
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintBetaPreamble(out.get());
|
||||
PrintGAServices(out.get());
|
||||
PrintBetaServices(out.get());
|
||||
}
|
||||
out->Print("except ImportError:\n");
|
||||
{
|
||||
IndentScope raii_dict_except_indent(out.get());
|
||||
out->Print("pass");
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
40
grpc/src/compiler/python_generator.h
Normal file
40
grpc/src/compiler/python_generator.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Data pertaining to configuration of the generator with respect to anything
|
||||
// that may be used internally at Google.
|
||||
struct GeneratorConfiguration {
|
||||
grpc::string grpc_package_root;
|
||||
// TODO(https://github.com/grpc/grpc/issues/8622): Drop this.
|
||||
grpc::string beta_package_root;
|
||||
// TODO(https://github.com/google/protobuf/issues/888): Drop this.
|
||||
grpc::string import_prefix;
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
72
grpc/src/compiler/python_private_generator.h
Normal file
72
grpc/src/compiler/python_private_generator.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Tucks all generator state in an anonymous namespace away from
|
||||
// PythonGrpcGenerator and the header file, mostly to encourage future changes
|
||||
// to not require updates to the grpcio-tools C++ code part. Assumes that it is
|
||||
// only ever used from a single thread.
|
||||
struct PrivateGenerator {
|
||||
const GeneratorConfiguration& config;
|
||||
const grpc_generator::File* file;
|
||||
|
||||
PrivateGenerator(const GeneratorConfiguration& config,
|
||||
const grpc_generator::File* file);
|
||||
|
||||
grpc::string GetGrpcServices();
|
||||
|
||||
private:
|
||||
void PrintPreamble(grpc_generator::Printer* out);
|
||||
void PrintBetaPreamble(grpc_generator::Printer* out);
|
||||
void PrintGAServices(grpc_generator::Printer* out);
|
||||
void PrintBetaServices(grpc_generator::Printer* out);
|
||||
|
||||
void PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintStub(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
|
||||
void PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
@@ -1,44 +1,29 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* 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
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
# include <string>
|
||||
# define GRPC_CUSTOM_STRING std::string
|
||||
@@ -79,6 +64,9 @@ struct Method : public CommentHolder {
|
||||
|
||||
virtual grpc::string get_input_type_name() const = 0;
|
||||
virtual grpc::string get_output_type_name() const = 0;
|
||||
|
||||
virtual grpc::string get_fb_builder() const = 0;
|
||||
|
||||
virtual bool NoStreaming() const = 0;
|
||||
virtual bool ClientStreaming() const = 0;
|
||||
virtual bool ServerStreaming() const = 0;
|
||||
|
||||
308
grpc/src/compiler/swift_generator.cc
Normal file
308
grpc/src/compiler/swift_generator.cc
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: The following implementation is a translation for the Swift-grpc
|
||||
* generator since flatbuffers doesnt allow plugins for now. if an issue arises
|
||||
* please open an issue in the flatbuffers repository. This file should always
|
||||
* be maintained according to the Swift-grpc repository
|
||||
*/
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
#include "src/compiler/swift_generator.h"
|
||||
|
||||
namespace grpc_swift_generator {
|
||||
|
||||
grpc::string GenerateMessage(const grpc::string &name) {
|
||||
return "Message<" + name + ">";
|
||||
}
|
||||
|
||||
// MARK: - Client
|
||||
|
||||
grpc::string GenerateClientFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$) -> UnaryCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$) -> "
|
||||
"ClientStreamingCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> ServerStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> BidirectionalStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
|
||||
grpc::string GenerateClientFuncBody(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "return self.makeUnaryCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "return self.makeClientStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "return self.makeServerStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions, handler: "
|
||||
"handler)";
|
||||
}
|
||||
return "return self.makeBidirectionalStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions, handler: handler)";
|
||||
}
|
||||
|
||||
void GenerateClientProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars, "$ACCESS$ protocol $ServiceName$Service {\n");
|
||||
vars["GenAccess"] = "";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = "";
|
||||
printer->Print("\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
void GenerateClientClass(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars,
|
||||
"$ACCESS$ final class $ServiceName$ServiceClient: GRPCClient, "
|
||||
"$ServiceName$Service {\n");
|
||||
printer->Print(vars, "\t$ACCESS$ let connection: ClientConnection\n");
|
||||
printer->Print(vars, "\t$ACCESS$ var defaultCallOptions: CallOptions\n");
|
||||
printer->Print("\n");
|
||||
printer->Print(vars,
|
||||
"\t$ACCESS$ init(connection: ClientConnection, "
|
||||
"defaultCallOptions: CallOptions = CallOptions()) {\n");
|
||||
printer->Print("\t\tself.connection = connection\n");
|
||||
printer->Print("\t\tself.defaultCallOptions = defaultCallOptions\n");
|
||||
printer->Print("\t}");
|
||||
printer->Print("\n");
|
||||
vars["GenAccess"] = "public";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = " = nil";
|
||||
printer->Print("\n\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print(" {\n");
|
||||
auto body = GenerateClientFuncBody(method.get());
|
||||
printer->Print("\t\t");
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n\t}\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
// MARK: - Server
|
||||
|
||||
grpc::string GenerateServerFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "func $MethodName$(_ request: $Input$"
|
||||
", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "func $MethodName$(context: UnaryResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<(StreamEvent<$Input$"
|
||||
">) -> Void>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "func $MethodName$(request: $Input$"
|
||||
", context: StreamingResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<GRPCStatus>";
|
||||
}
|
||||
return "func $MethodName$(context: StreamingResponseCallContext<$Output$>) "
|
||||
"-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>";
|
||||
}
|
||||
|
||||
grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) {
|
||||
grpc::string start = "\t\tcase \"$MethodName$\":\n\t\t";
|
||||
if (method->NoStreaming()) {
|
||||
return start +
|
||||
"return UnaryCallHandler(callHandlerContext: callHandlerContext) { "
|
||||
"context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ClientStreaming()) {
|
||||
return start +
|
||||
"return ClientStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ServerStreaming()) {
|
||||
return start +
|
||||
"return ServerStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->BidiStreaming()) {
|
||||
return start +
|
||||
"return BidirectionalStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void GenerateServerProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(
|
||||
vars, "$ACCESS$ protocol $ServiceName$Provider: CallHandlerProvider {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
printer->Print("\t");
|
||||
auto func = GenerateServerFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
|
||||
printer->Print(vars, "$ACCESS$ extension $ServiceName$Provider {\n");
|
||||
printer->Print(vars,
|
||||
"\tvar serviceName: String { return "
|
||||
"\"$PATH$$ServiceName$\" }\n");
|
||||
printer->Print(
|
||||
"\tfunc handleMethod(_ methodName: String, callHandlerContext: "
|
||||
"CallHandlerContext) -> GRPCCallHandler? {\n");
|
||||
printer->Print("\t\tswitch methodName {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
auto body = GenerateServerExtensionBody(method.get());
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("\t\tdefault: return nil;\n");
|
||||
printer->Print("\t\t}\n");
|
||||
printer->Print("\t}\n\n");
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service) {
|
||||
grpc::string output;
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
vars["PATH"] = file->package();
|
||||
if (!file->package().empty()) { vars["PATH"].append("."); }
|
||||
vars["ServiceName"] = service->name();
|
||||
vars["ACCESS"] = "public";
|
||||
auto printer = file->CreatePrinter(&output);
|
||||
printer->Print(vars,
|
||||
"/// Usage: instantiate $ServiceName$ServiceClient, then call "
|
||||
"methods of this protocol to make API calls.\n");
|
||||
GenerateClientProtocol(service, &*printer, &vars);
|
||||
GenerateClientClass(service, &*printer, &vars);
|
||||
printer->Print("\n");
|
||||
GenerateServerProtocol(service, &*printer, &vars);
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GenerateHeader() {
|
||||
grpc::string code;
|
||||
code +=
|
||||
"/// The following code is generated by the Flatbuffers library which "
|
||||
"might not be in sync with grpc-swift\n";
|
||||
code +=
|
||||
"/// in case of an issue please open github issue, though it would be "
|
||||
"maintained\n";
|
||||
code += "import Foundation\n";
|
||||
code += "import GRPC\n";
|
||||
code += "import NIO\n";
|
||||
code += "import NIOHTTP1\n";
|
||||
code += "import FlatBuffers\n";
|
||||
code += "\n";
|
||||
code +=
|
||||
"public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage "
|
||||
"{}\n";
|
||||
|
||||
code += "public extension GRPCFlatBufPayload {\n";
|
||||
code += " init(serializedByteBuffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: "
|
||||
"serializedByteBuffer.readableBytesView, count: "
|
||||
"serializedByteBuffer.readableBytes))\n";
|
||||
code += " }\n";
|
||||
|
||||
code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
|
||||
"Int(self.size))\n";
|
||||
code += " buffer.writeBytes(buf)\n";
|
||||
code += " }\n";
|
||||
code += "}\n";
|
||||
code += "extension Message: GRPCFlatBufPayload {}\n";
|
||||
return code;
|
||||
}
|
||||
} // namespace grpc_swift_generator
|
||||
55
grpc/src/compiler/swift_generator.h
Normal file
55
grpc/src/compiler/swift_generator.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
# include <string>
|
||||
# define GRPC_CUSTOM_STRING std::string
|
||||
#endif
|
||||
|
||||
namespace grpc {
|
||||
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
namespace grpc_swift_generator {
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service);
|
||||
grpc::string GenerateHeader();
|
||||
} // namespace grpc_swift_generator
|
||||
42
grpc/tests/GameFactory.java
Normal file
42
grpc/tests/GameFactory.java
Normal file
@@ -0,0 +1,42 @@
|
||||
import java.nio.ByteBuffer;
|
||||
import MyGame.Example.Monster;
|
||||
import MyGame.Example.Stat;
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
|
||||
class GameFactory {
|
||||
public static Monster createMonster(String monsterName, short nestedMonsterHp, short nestedMonsterMana) {
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
|
||||
int name_offset = builder.createString(monsterName);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, name_offset);
|
||||
Monster.addHp(builder, nestedMonsterHp);
|
||||
Monster.addMana(builder, nestedMonsterMana);
|
||||
int monster_offset = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, monster_offset);
|
||||
|
||||
ByteBuffer buffer = builder.dataBuffer();
|
||||
Monster monster = Monster.getRootAsMonster(buffer);
|
||||
return monster;
|
||||
}
|
||||
|
||||
public static Monster createMonsterFromStat(Stat stat, int seqNo) {
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int name_offset = builder.createString(stat.id() + " No." + seqNo);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, name_offset);
|
||||
int monster_offset = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, monster_offset);
|
||||
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
|
||||
return monster;
|
||||
}
|
||||
|
||||
public static Stat createStat(String greeting, long val, int count) {
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int statOffset = Stat.createStat(builder, builder.createString(greeting), val, count);
|
||||
builder.finish(statOffset);
|
||||
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
|
||||
return stat;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,21 +22,32 @@ import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.InterruptedException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
|
||||
/**
|
||||
* Demonstrates basic client-server interaction using grpc-java over netty.
|
||||
*/
|
||||
public class JavaGrpcTest {
|
||||
static final String BIG_MONSTER_NAME = "big-monster";
|
||||
static final String BIG_MONSTER_NAME = "Cyberdemon";
|
||||
static final short nestedMonsterHp = 600;
|
||||
static final short nestedMonsterMana = 1024;
|
||||
static final int numStreamedMsgs = 10;
|
||||
static final int timeoutMs = 3000;
|
||||
static Server server;
|
||||
static ManagedChannel channel;
|
||||
static MonsterStorageGrpc.MonsterStorageBlockingStub blockingStub;
|
||||
static MonsterStorageGrpc.MonsterStorageStub asyncStub;
|
||||
|
||||
static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
|
||||
@Override
|
||||
@@ -46,10 +57,7 @@ public class JavaGrpcTest {
|
||||
Assert.assertEquals(request.mana(), nestedMonsterMana);
|
||||
System.out.println("Received store request from " + request.name());
|
||||
// Create a response from the incoming request name.
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int statOffset = Stat.createStat(builder, builder.createString("Hello " + request.name()), 100, 10);
|
||||
builder.finish(statOffset);
|
||||
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
|
||||
Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10);
|
||||
responseObserver.onNext(stat);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
@@ -58,55 +66,101 @@ public class JavaGrpcTest {
|
||||
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
|
||||
// Create 10 monsters for streaming response.
|
||||
for (int i=0; i<numStreamedMsgs; i++) {
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int i1 = builder.createString(request.id() + " No." + i);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, i1);
|
||||
int i2 = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, i2);
|
||||
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
|
||||
Monster monster = GameFactory.createMonsterFromStat(request, i);
|
||||
responseObserver.onNext(monster);
|
||||
}
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<Monster> getMaxHitPoint(final StreamObserver<Stat> responseObserver) {
|
||||
return computeMinMax(responseObserver, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<Monster> getMinMaxHitPoints(final StreamObserver<Stat> responseObserver) {
|
||||
return computeMinMax(responseObserver, true);
|
||||
}
|
||||
|
||||
private StreamObserver<Monster> computeMinMax(final StreamObserver<Stat> responseObserver, final boolean includeMin) {
|
||||
final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE);
|
||||
final AtomicReference<String> maxHpMonsterName = new AtomicReference<String>();
|
||||
final AtomicInteger maxHpCount = new AtomicInteger();
|
||||
|
||||
final AtomicInteger minHp = new AtomicInteger(Integer.MAX_VALUE);
|
||||
final AtomicReference<String> minHpMonsterName = new AtomicReference<String>();
|
||||
final AtomicInteger minHpCount = new AtomicInteger();
|
||||
|
||||
return new StreamObserver<Monster>() {
|
||||
public void onNext(Monster monster) {
|
||||
if (monster.hp() > maxHp.get()) {
|
||||
// Found a monster of higher hit points.
|
||||
maxHp.set(monster.hp());
|
||||
maxHpMonsterName.set(monster.name());
|
||||
maxHpCount.set(1);
|
||||
}
|
||||
else if (monster.hp() == maxHp.get()) {
|
||||
// Count how many times we saw a monster of current max hit points.
|
||||
maxHpCount.getAndIncrement();
|
||||
}
|
||||
|
||||
if (monster.hp() < minHp.get()) {
|
||||
// Found a monster of a lower hit points.
|
||||
minHp.set(monster.hp());
|
||||
minHpMonsterName.set(monster.name());
|
||||
minHpCount.set(1);
|
||||
}
|
||||
else if (monster.hp() == minHp.get()) {
|
||||
// Count how many times we saw a monster of current min hit points.
|
||||
minHpCount.getAndIncrement();
|
||||
}
|
||||
}
|
||||
public void onCompleted() {
|
||||
Stat maxHpStat = GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get());
|
||||
// Send max hit points first.
|
||||
responseObserver.onNext(maxHpStat);
|
||||
if (includeMin) {
|
||||
// Send min hit points.
|
||||
Stat minHpStat = GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get());
|
||||
responseObserver.onNext(minHpStat);
|
||||
}
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
public void onError(Throwable t) {
|
||||
// Not expected
|
||||
Assert.fail();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int startServer() throws IOException {
|
||||
Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||
return server.getPort();
|
||||
@org.junit.BeforeClass
|
||||
public static void startServer() throws IOException {
|
||||
server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||
int port = server.getPort();
|
||||
channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext()
|
||||
.directExecutor()
|
||||
.build();
|
||||
blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||
asyncStub = MonsterStorageGrpc.newStub(channel);
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void testMonster() throws IOException {
|
||||
int port = startServer();
|
||||
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext(true)
|
||||
.directExecutor()
|
||||
.build();
|
||||
|
||||
MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
|
||||
int o_string = builder.createString(BIG_MONSTER_NAME);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, o_string);
|
||||
Monster.addHp(builder, nestedMonsterHp);
|
||||
Monster.addMana(builder, nestedMonsterMana);
|
||||
int monster1 = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, monster1);
|
||||
|
||||
ByteBuffer buffer = builder.dataBuffer();
|
||||
Monster monsterRequest = Monster.getRootAsMonster(buffer);
|
||||
Stat stat = stub.store(monsterRequest);
|
||||
public void testUnary() throws IOException {
|
||||
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
|
||||
Stat stat = blockingStub.store(monsterRequest);
|
||||
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
|
||||
System.out.println("Received stat response from service: " + stat.id());
|
||||
}
|
||||
|
||||
|
||||
Iterator<Monster> iterator = stub.retrieve(stat);
|
||||
@org.junit.Test
|
||||
public void testServerStreaming() throws IOException {
|
||||
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
|
||||
Stat stat = blockingStub.store(monsterRequest);
|
||||
Iterator<Monster> iterator = blockingStub.retrieve(stat);
|
||||
int counter = 0;
|
||||
while(iterator.hasNext()) {
|
||||
Monster m = iterator.next();
|
||||
@@ -116,4 +170,73 @@ public class JavaGrpcTest {
|
||||
Assert.assertEquals(counter, numStreamedMsgs);
|
||||
System.out.println("FlatBuffers GRPC client/server test: completed successfully");
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void testClientStreaming() throws IOException, InterruptedException {
|
||||
final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
|
||||
final CountDownLatch streamAlive = new CountDownLatch(1);
|
||||
|
||||
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
|
||||
public void onCompleted() {
|
||||
streamAlive.countDown();
|
||||
}
|
||||
public void onError(Throwable ex) { }
|
||||
public void onNext(Stat stat) {
|
||||
maxHitStat.set(stat);
|
||||
}
|
||||
};
|
||||
StreamObserver<Monster> monsterStream = asyncStub.getMaxHitPoint(statObserver);
|
||||
short count = 10;
|
||||
for (short i = 0;i < count; ++i) {
|
||||
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
|
||||
monsterStream.onNext(monster);
|
||||
}
|
||||
monsterStream.onCompleted();
|
||||
// Wait a little bit for the server to send the stats of the monster with the max hit-points.
|
||||
streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||
Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
|
||||
Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
|
||||
Assert.assertEquals(maxHitStat.get().count(), 1);
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void testBiDiStreaming() throws IOException, InterruptedException {
|
||||
final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
|
||||
final AtomicReference<Stat> minHitStat = new AtomicReference<Stat>();
|
||||
final CountDownLatch streamAlive = new CountDownLatch(1);
|
||||
|
||||
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
|
||||
public void onCompleted() {
|
||||
streamAlive.countDown();
|
||||
}
|
||||
public void onError(Throwable ex) { }
|
||||
public void onNext(Stat stat) {
|
||||
// We expect the server to send the max stat first and then the min stat.
|
||||
if (maxHitStat.get() == null) {
|
||||
maxHitStat.set(stat);
|
||||
}
|
||||
else {
|
||||
minHitStat.set(stat);
|
||||
}
|
||||
}
|
||||
};
|
||||
StreamObserver<Monster> monsterStream = asyncStub.getMinMaxHitPoints(statObserver);
|
||||
short count = 10;
|
||||
for (short i = 0;i < count; ++i) {
|
||||
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
|
||||
monsterStream.onNext(monster);
|
||||
}
|
||||
monsterStream.onCompleted();
|
||||
|
||||
// Wait a little bit for the server to send the stats of the monster with the max and min hit-points.
|
||||
streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||
|
||||
Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
|
||||
Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
|
||||
Assert.assertEquals(maxHitStat.get().count(), 1);
|
||||
|
||||
Assert.assertEquals(minHitStat.get().id(), BIG_MONSTER_NAME + 0);
|
||||
Assert.assertEquals(minHitStat.get().val(), nestedMonsterHp * 0);
|
||||
Assert.assertEquals(minHitStat.get().count(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package testing
|
||||
import (
|
||||
"../../tests/MyGame/Example"
|
||||
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
||||
@@ -14,14 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "monster_test.grpc.fb.h"
|
||||
#include "monster_test_generated.h"
|
||||
#include "test_assert.h"
|
||||
|
||||
using namespace MyGame::Example;
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
void message_builder_tests();
|
||||
|
||||
// The callback implementation of our server, that derives from the generated
|
||||
// code. It implements all rpcs specified in the FlatBuffers schema.
|
||||
@@ -44,9 +49,9 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
||||
const flatbuffers::grpc::Message<Stat> *request,
|
||||
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
|
||||
override {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
fbb_.Clear();
|
||||
// Create 10 monsters for resposne.
|
||||
// Create 5 monsters for resposne.
|
||||
auto monster_offset =
|
||||
CreateMonster(fbb_, 0, 0, 0,
|
||||
fbb_.CreateString(request->GetRoot()->id()->str() +
|
||||
@@ -92,7 +97,44 @@ void RunServer() {
|
||||
server_instance->Wait();
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
template<class Builder> void StoreRPC(MonsterStorage::Stub *stub) {
|
||||
Builder fbb;
|
||||
grpc::ClientContext context;
|
||||
// Build a request with the name set.
|
||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||
MessageBuilder mb(std::move(fbb));
|
||||
mb.Finish(monster_offset);
|
||||
auto request = mb.ReleaseMessage<Monster>();
|
||||
flatbuffers::grpc::Message<Stat> response;
|
||||
|
||||
// The actual RPC.
|
||||
auto status = stub->Store(&context, request, &response);
|
||||
|
||||
if (status.ok()) {
|
||||
auto resp = response.GetRoot()->id();
|
||||
std::cout << "RPC response: " << resp->str() << std::endl;
|
||||
} else {
|
||||
std::cout << "RPC failed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Builder> void RetrieveRPC(MonsterStorage::Stub *stub) {
|
||||
Builder fbb;
|
||||
grpc::ClientContext context;
|
||||
fbb.Clear();
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
|
||||
fbb.Finish(stat_offset);
|
||||
auto request = MessageBuilder(std::move(fbb)).ReleaseMessage<Stat>();
|
||||
|
||||
flatbuffers::grpc::Message<Monster> response;
|
||||
auto stream = stub->Retrieve(&context, request);
|
||||
while (stream->Read(&response)) {
|
||||
auto resp = response.GetRoot()->name();
|
||||
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int grpc_server_test() {
|
||||
// Launch server.
|
||||
std::thread server_thread(RunServer);
|
||||
|
||||
@@ -105,39 +147,11 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
grpc::InsecureChannelCredentials());
|
||||
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
|
||||
|
||||
flatbuffers::grpc::MessageBuilder fbb;
|
||||
{
|
||||
grpc::ClientContext context;
|
||||
// Build a request with the name set.
|
||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||
fbb.Finish(monster_offset);
|
||||
auto request = fbb.ReleaseMessage<Monster>();
|
||||
flatbuffers::grpc::Message<Stat> response;
|
||||
StoreRPC<MessageBuilder>(stub.get());
|
||||
StoreRPC<FlatBufferBuilder>(stub.get());
|
||||
|
||||
// The actual RPC.
|
||||
auto status = stub->Store(&context, request, &response);
|
||||
|
||||
if (status.ok()) {
|
||||
auto resp = response.GetRoot()->id();
|
||||
std::cout << "RPC response: " << resp->str() << std::endl;
|
||||
} else {
|
||||
std::cout << "RPC failed" << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
grpc::ClientContext context;
|
||||
fbb.Clear();
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
|
||||
fbb.Finish(stat_offset);
|
||||
auto request = fbb.ReleaseMessage<Stat>();
|
||||
|
||||
flatbuffers::grpc::Message<Monster> response;
|
||||
auto stream = stub->Retrieve(&context, request);
|
||||
while (stream->Read(&response)) {
|
||||
auto resp = response.GetRoot()->name();
|
||||
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
|
||||
}
|
||||
}
|
||||
RetrieveRPC<MessageBuilder>(stub.get());
|
||||
RetrieveRPC<FlatBufferBuilder>(stub.get());
|
||||
|
||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
{
|
||||
@@ -163,3 +177,16 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
message_builder_tests();
|
||||
grpc_server_test();
|
||||
|
||||
if (!testing_fails) {
|
||||
TEST_OUTPUT_LINE("ALL TESTS PASSED");
|
||||
return 0;
|
||||
} else {
|
||||
TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
174
grpc/tests/grpctest.py
Normal file
174
grpc/tests/grpctest.py
Normal file
@@ -0,0 +1,174 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import grpc
|
||||
import flatbuffers
|
||||
|
||||
from concurrent import futures
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests'))
|
||||
import MyGame.Example.Monster as Monster
|
||||
import MyGame.Example.Stat as Stat
|
||||
import MyGame.Example.Vec3 as Vec3
|
||||
import MyGame.Example.Test as Test
|
||||
import MyGame.Example.monster_test_grpc_fb as monster_grpc_fb
|
||||
|
||||
|
||||
test_stat_id = "test_stat_id"
|
||||
test_stat_val = 8
|
||||
test_stat_count = 1
|
||||
|
||||
test_monster_name1 = "test_monster_name1"
|
||||
test_monster_name2 = "test_monster_name2"
|
||||
test_string = "test_string"
|
||||
test_color = 2
|
||||
test_X = 3.0
|
||||
test_Y = 2.0
|
||||
test_Z = 6.0
|
||||
test_test1 = 4.0
|
||||
test_a = 8
|
||||
test_b = 5
|
||||
test_hp = 67
|
||||
test_inventory = [1, 1, 2, 3, 5, 8]
|
||||
test_testtype = 4
|
||||
|
||||
test_monsters_name_retrieve = ["big_monster", "small_monster"]
|
||||
test_no_of_monsters = 2
|
||||
|
||||
|
||||
class MonsterStorage(monster_grpc_fb.MonsterStorageServicer):
|
||||
|
||||
def Store(self, request, context):
|
||||
|
||||
m = Monster.Monster().GetRootAsMonster(request, 0)
|
||||
|
||||
assert m.Name().decode("utf-8") == test_monster_name1
|
||||
|
||||
assert m.Pos().X() == test_X
|
||||
assert m.Pos().Y() == test_Y
|
||||
assert m.Pos().Z() == test_Z
|
||||
assert m.Pos().Test1() == test_test1
|
||||
assert m.Pos().Test2() == test_color
|
||||
test3 = Test.Test()
|
||||
assert m.Pos().Test3(test3).A() == test_a
|
||||
assert m.Pos().Test3(test3).B() == test_b
|
||||
|
||||
assert m.Hp() == test_hp
|
||||
|
||||
assert m.Color() == test_color
|
||||
|
||||
assert m.InventoryLength() == len(test_inventory)
|
||||
for i in range(0, len(test_inventory)):
|
||||
assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1]
|
||||
|
||||
assert m.TestType() == test_testtype
|
||||
|
||||
assert m.Test() is not None
|
||||
table = m.Test()
|
||||
|
||||
m2 = Monster.Monster()
|
||||
m2.Init(table.Bytes, table.Pos)
|
||||
assert m2.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
m3 = m.Enemy()
|
||||
assert m3.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
assert m.Testarrayofstring(0).decode("utf-8") == test_string
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_stat_id)
|
||||
Stat.StatStart(b)
|
||||
Stat.StatAddId(b, i)
|
||||
Stat.StatAddVal(b, test_stat_val)
|
||||
Stat.StatAddCount(b, test_stat_count)
|
||||
b.Finish(Stat.StatEnd(b))
|
||||
return bytes(b.Output())
|
||||
|
||||
def Retrieve(self, request, context):
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(request, 0)
|
||||
|
||||
no_of_monsters = test_no_of_monsters
|
||||
for i in range(0, no_of_monsters):
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_monsters_name_retrieve[i])
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, i)
|
||||
b.Finish(Monster.MonsterEnd(b))
|
||||
yield bytes(b.Output())
|
||||
|
||||
|
||||
def serve():
|
||||
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server)
|
||||
server.add_insecure_port('[::]:50051')
|
||||
|
||||
server.start()
|
||||
|
||||
run()
|
||||
|
||||
|
||||
def run():
|
||||
|
||||
channel = grpc.insecure_channel('127.0.0.1:50051')
|
||||
stub = monster_grpc_fb.MonsterStorageStub(channel)
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
name2 = b.CreateString(test_monster_name2)
|
||||
name1 = b.CreateString(test_monster_name1)
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, name2)
|
||||
monster2 = Monster.MonsterEnd(b)
|
||||
test1 = b.CreateString(test_string)
|
||||
|
||||
Monster.MonsterStartInventoryVector(b, len(test_inventory))
|
||||
for i in range(0, len(test_inventory)):
|
||||
b.PrependByte(test_inventory[i])
|
||||
inv = b.EndVector(len(test_inventory))
|
||||
|
||||
Monster.MonsterStartTest4Vector(b, 2)
|
||||
Test.CreateTest(b, 10, 20)
|
||||
Test.CreateTest(b, 30, 40)
|
||||
test4 = b.EndVector(2)
|
||||
|
||||
Monster.MonsterStartTestarrayofstringVector(b, 1)
|
||||
b.PrependUOffsetTRelative(test1)
|
||||
test_array_of_string = b.EndVector(1)
|
||||
|
||||
Monster.MonsterStart(b)
|
||||
|
||||
Monster.MonsterAddHp(b, test_hp)
|
||||
Monster.MonsterAddName(b, name1)
|
||||
Monster.MonsterAddColor(b, test_color)
|
||||
pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b)
|
||||
Monster.MonsterAddPos(b, pos)
|
||||
Monster.MonsterAddInventory(b, inv)
|
||||
Monster.MonsterAddTestType(b, test_testtype)
|
||||
Monster.MonsterAddTest(b, monster2)
|
||||
Monster.MonsterAddTest4(b, test4)
|
||||
Monster.MonsterAddEnemy(b, monster2)
|
||||
Monster.MonsterAddTestarrayofstring(b, test_array_of_string)
|
||||
monster = Monster.MonsterEnd(b)
|
||||
|
||||
b.Finish(monster)
|
||||
|
||||
stat_response = stub.Store(bytes(b.Output()))
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(stat_response, 0)
|
||||
|
||||
assert s.Id().decode("utf-8") == test_stat_id
|
||||
assert s.Val() == test_stat_val
|
||||
assert s.Count() == test_stat_count
|
||||
|
||||
monster_reponses = stub.Retrieve(stat_response)
|
||||
count = 0
|
||||
for monster_reponse in monster_reponses:
|
||||
m = Monster.Monster().GetRootAsMonster(monster_reponse, 0)
|
||||
assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count]
|
||||
count = count + 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
serve()
|
||||
371
grpc/tests/message_builder_test.cpp
Normal file
371
grpc/tests/message_builder_test.cpp
Normal file
@@ -0,0 +1,371 @@
|
||||
#include "flatbuffers/grpc.h"
|
||||
#include "monster_test_generated.h"
|
||||
#include "test_assert.h"
|
||||
#include "test_builder.h"
|
||||
|
||||
using MyGame::Example::Any_NONE;
|
||||
using MyGame::Example::CreateStat;
|
||||
using MyGame::Example::Vec3;
|
||||
|
||||
bool verify(flatbuffers::grpc::Message<Monster> &msg,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
const Monster *monster = msg.GetRoot();
|
||||
const auto name = monster->name()->str();
|
||||
const auto color = monster->color();
|
||||
TEST_EQ(name, expected_name);
|
||||
TEST_EQ(color, expected_color);
|
||||
return (name == expected_name) && (color == expected_color);
|
||||
}
|
||||
|
||||
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
|
||||
return verify(msg, expected_name, expected_color);
|
||||
}
|
||||
|
||||
void builder_move_assign_after_releaseraw_test(
|
||||
flatbuffers::grpc::MessageBuilder dst) {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
dst.ReleaseRaw(size, offset, slice);
|
||||
flatbuffers::FlatBufferBuilder src;
|
||||
auto root_offset2 = populate2(src);
|
||||
src.Finish(root_offset2);
|
||||
auto src_size = src.GetSize();
|
||||
// Move into a released builder.
|
||||
dst = std::move(src);
|
||||
TEST_EQ(dst.GetSize(), src_size);
|
||||
TEST_ASSERT(release_n_verify(dst, m2_name(), m2_color()));
|
||||
TEST_EQ(src.GetSize(), 0);
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
|
||||
template<class SrcBuilder>
|
||||
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
static void builder_reusable_after_release_message_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
buffers.push_back(mb.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
|
||||
|
||||
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
|
||||
// SliceAllocator::allocate in the second iteration.
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
buffers.push_back(mb.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_releaseraw_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
|
||||
|
||||
// FIXME: Release-move_assign loop fails assert(p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the
|
||||
// iterations
|
||||
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
buffers.push_back(dst.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
|
||||
// bring dst back to life.
|
||||
SrcBuilder src;
|
||||
dst = std::move(src);
|
||||
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_message_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
buffers.push_back(dst.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
|
||||
// bring dst back to life.
|
||||
SrcBuilder src;
|
||||
dst = std::move(src);
|
||||
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_releaseraw_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice = grpc_empty_slice();
|
||||
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
|
||||
SrcBuilder src;
|
||||
dst = std::move(src);
|
||||
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void run_tests(TestSelector selector) {
|
||||
builder_reusable_after_release_test(selector);
|
||||
builder_reusable_after_release_message_test(selector);
|
||||
builder_reusable_after_releaseraw_test(selector);
|
||||
builder_reusable_after_release_and_move_assign_test(selector);
|
||||
builder_reusable_after_releaseraw_and_move_assign_test(selector);
|
||||
builder_reusable_after_release_message_and_move_assign_test(selector);
|
||||
}
|
||||
};
|
||||
|
||||
void slice_allocator_tests() {
|
||||
// move-construct no-delete test
|
||||
{
|
||||
size_t size = 2048;
|
||||
flatbuffers::grpc::SliceAllocator sa1;
|
||||
uint8_t *buf = sa1.allocate(size);
|
||||
TEST_ASSERT_FUNC(buf != 0);
|
||||
buf[0] = 100;
|
||||
buf[size - 1] = 200;
|
||||
flatbuffers::grpc::SliceAllocator sa2(std::move(sa1));
|
||||
// buf should not be deleted after move-construct
|
||||
TEST_EQ_FUNC(buf[0], 100);
|
||||
TEST_EQ_FUNC(buf[size - 1], 200);
|
||||
// buf is freed here
|
||||
}
|
||||
|
||||
// move-assign test
|
||||
{
|
||||
flatbuffers::grpc::SliceAllocator sa1, sa2;
|
||||
uint8_t *buf = sa1.allocate(2048);
|
||||
sa1 = std::move(sa2);
|
||||
// sa1 deletes previously allocated memory in move-assign.
|
||||
// So buf is no longer usable here.
|
||||
TEST_ASSERT_FUNC(buf != 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This function does not populate exactly the first half of the table. But it
|
||||
/// could.
|
||||
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper,
|
||||
flatbuffers::Offset<flatbuffers::String> name_offset) {
|
||||
wrapper.add_name(name_offset);
|
||||
wrapper.add_color(m1_color());
|
||||
}
|
||||
|
||||
/// This function does not populate exactly the second half of the table. But it
|
||||
/// could.
|
||||
void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
|
||||
wrapper.add_hp(77);
|
||||
wrapper.add_mana(88);
|
||||
Vec3 vec3;
|
||||
wrapper.add_pos(&vec3);
|
||||
}
|
||||
|
||||
/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in
|
||||
/// the MonsterBuilder object. This function will break if fbb_ is not the first
|
||||
/// member in MonsterBuilder. In that case, some offset must be added. This
|
||||
/// function is used exclusively for testing correctness of move operations
|
||||
/// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack
|
||||
/// would be unnecessary. That involves a code-generator change though.
|
||||
void test_only_hack_update_fbb_reference(
|
||||
MyGame::Example::MonsterBuilder &monsterBuilder,
|
||||
flatbuffers::grpc::MessageBuilder &mb) {
|
||||
*reinterpret_cast<flatbuffers::FlatBufferBuilder **>(&monsterBuilder) = &mb;
|
||||
}
|
||||
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a
|
||||
/// MessageBuilder DURING a table construction. Half of the table is constructed
|
||||
/// using FlatBufferBuilder and the other half of the table is constructed using
|
||||
/// a MessageBuilder.
|
||||
void builder_move_ctor_conversion_before_finish_half_n_half_table_test() {
|
||||
for (size_t initial_size = 4; initial_size <= 2048; initial_size *= 2) {
|
||||
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||
auto name_offset = fbb.CreateString(m1_name());
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(
|
||||
fbb); // starts a table in FlatBufferBuilder
|
||||
populate_first_half(monsterBuilder, name_offset);
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
populate_second_half(monsterBuilder);
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates a COMPLETE inner table before move conversion and later
|
||||
/// populates more members in the outer table.
|
||||
void builder_move_ctor_conversion_before_finish_test() {
|
||||
for (size_t initial_size = 1; initial_size <= 2048; initial_size += 1) {
|
||||
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
auto monster_offset =
|
||||
CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
|
||||
m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
mb.Finish(monster_offset);
|
||||
{
|
||||
auto mon = flatbuffers::GetRoot<Monster>(mb.GetBufferPointer());
|
||||
TEST_NOTNULL(mon);
|
||||
TEST_NOTNULL(mon->name());
|
||||
TEST_EQ_STR(mon->name()->c_str(), m1_name().c_str());
|
||||
TEST_EQ(mon->color(), m1_color());
|
||||
}
|
||||
TEST_EQ(1, MyGame::Example::Color_Red);
|
||||
TEST_EQ(1, m1_color());
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a
|
||||
/// MessageBuilder DURING a table construction. Half of the table is constructed
|
||||
/// using FlatBufferBuilder and the other half of the table is constructed using
|
||||
/// a MessageBuilder.
|
||||
void builder_move_assign_conversion_before_finish_half_n_half_table_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
auto name_offset = fbb.CreateString(m1_name());
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(
|
||||
fbb); // starts a table in FlatBufferBuilder
|
||||
populate_first_half(monsterBuilder, name_offset);
|
||||
mb = std::move(fbb);
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
populate_second_half(monsterBuilder);
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates a COMPLETE inner table before move conversion and later
|
||||
/// populates more members in the outer table.
|
||||
void builder_move_assign_conversion_before_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||
mb = std::move(fbb);
|
||||
auto monster_offset =
|
||||
CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
|
||||
m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
mb.Finish(monster_offset);
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates data, finishes the buffer, and does move conversion
|
||||
/// after.
|
||||
void builder_move_ctor_conversion_after_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
fbb.Finish(populate1(fbb));
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
|
||||
/// This test populates data, finishes the buffer, and does move conversion
|
||||
/// after.
|
||||
void builder_move_assign_conversion_after_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
fbb.Finish(populate1(fbb));
|
||||
mb = std::move(fbb);
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void message_builder_tests() {
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
slice_allocator_tests();
|
||||
|
||||
#ifndef __APPLE__
|
||||
builder_move_ctor_conversion_before_finish_half_n_half_table_test();
|
||||
builder_move_assign_conversion_before_finish_half_n_half_table_test();
|
||||
#endif // __APPLE__
|
||||
builder_move_ctor_conversion_before_finish_test();
|
||||
builder_move_assign_conversion_before_finish_test();
|
||||
|
||||
builder_move_ctor_conversion_after_finish_test();
|
||||
builder_move_assign_conversion_after_finish_test();
|
||||
|
||||
BuilderTests<MessageBuilder, MessageBuilder>::all_tests();
|
||||
BuilderTests<MessageBuilder, FlatBufferBuilder>::all_tests();
|
||||
|
||||
BuilderReuseTestSelector tests[6] = {
|
||||
// REUSABLE_AFTER_RELEASE, // Assertion failed:
|
||||
// (GRPC_SLICE_IS_EMPTY(slice_))
|
||||
// REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)
|
||||
|
||||
REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
|
||||
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
|
||||
};
|
||||
|
||||
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user