@layerzerolabs/layerzero-v2-ton 3.0.12-ton.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +15 -0
  3. package/build/AllStorages.boc +0 -0
  4. package/build/AllStorages.compiled.json +1 -0
  5. package/build/AllStorages.fif +4164 -0
  6. package/build/AllStorages.test.boc +0 -0
  7. package/build/AllStorages.test.compiled.json +1 -0
  8. package/build/AllStorages.test.fif +1831 -0
  9. package/build/BaseContract.test.boc +0 -0
  10. package/build/BaseContract.test.compiled.json +1 -0
  11. package/build/BaseContract.test.fif +3553 -0
  12. package/build/Channel.boc +0 -0
  13. package/build/Channel.compiled.json +1 -0
  14. package/build/Channel.fif +5001 -0
  15. package/build/Channel.permissions.test.boc +0 -0
  16. package/build/Channel.permissions.test.compiled.json +1 -0
  17. package/build/Channel.permissions.test.fif +7569 -0
  18. package/build/ChannelBurn.test.boc +0 -0
  19. package/build/ChannelBurn.test.compiled.json +1 -0
  20. package/build/ChannelBurn.test.fif +7454 -0
  21. package/build/ChannelCommitPacket.test.boc +0 -0
  22. package/build/ChannelCommitPacket.test.compiled.json +1 -0
  23. package/build/ChannelCommitPacket.test.fif +7981 -0
  24. package/build/ChannelConfig.test.boc +0 -0
  25. package/build/ChannelConfig.test.compiled.json +1 -0
  26. package/build/ChannelConfig.test.fif +7442 -0
  27. package/build/ChannelInitialize.test.boc +0 -0
  28. package/build/ChannelInitialize.test.compiled.json +1 -0
  29. package/build/ChannelInitialize.test.fif +7289 -0
  30. package/build/ChannelMsglibIntegration.test.boc +0 -0
  31. package/build/ChannelMsglibIntegration.test.compiled.json +1 -0
  32. package/build/ChannelMsglibIntegration.test.fif +7404 -0
  33. package/build/ChannelMsglibSendCallback.test.boc +0 -0
  34. package/build/ChannelMsglibSendCallback.test.compiled.json +1 -0
  35. package/build/ChannelMsglibSendCallback.test.fif +7711 -0
  36. package/build/ChannelNilify.test.boc +0 -0
  37. package/build/ChannelNilify.test.compiled.json +1 -0
  38. package/build/ChannelNilify.test.fif +7672 -0
  39. package/build/ChannelReceive.test.boc +0 -0
  40. package/build/ChannelReceive.test.compiled.json +1 -0
  41. package/build/ChannelReceive.test.fif +7702 -0
  42. package/build/ChannelReceiveCallback.test.boc +0 -0
  43. package/build/ChannelReceiveCallback.test.compiled.json +1 -0
  44. package/build/ChannelReceiveCallback.test.fif +7549 -0
  45. package/build/ChannelReceiveView.test.boc +0 -0
  46. package/build/ChannelReceiveView.test.compiled.json +1 -0
  47. package/build/ChannelReceiveView.test.fif +7352 -0
  48. package/build/ChannelSend.test.boc +0 -0
  49. package/build/ChannelSend.test.compiled.json +1 -0
  50. package/build/ChannelSend.test.fif +7658 -0
  51. package/build/Classlib.test.boc +0 -0
  52. package/build/Classlib.test.compiled.json +1 -0
  53. package/build/Classlib.test.fif +4728 -0
  54. package/build/Connection.boc +0 -0
  55. package/build/Connection.compiled.json +1 -0
  56. package/build/Connection.fif +3503 -0
  57. package/build/Connection.test.boc +0 -0
  58. package/build/Connection.test.compiled.json +1 -0
  59. package/build/Connection.test.fif +6575 -0
  60. package/build/Controller.assertions.test.boc +0 -0
  61. package/build/Controller.assertions.test.compiled.json +1 -0
  62. package/build/Controller.assertions.test.fif +6130 -0
  63. package/build/Controller.boc +0 -0
  64. package/build/Controller.compiled.json +1 -0
  65. package/build/Controller.fif +3195 -0
  66. package/build/Controller.permissions.test.boc +0 -0
  67. package/build/Controller.permissions.test.compiled.json +1 -0
  68. package/build/Controller.permissions.test.fif +6237 -0
  69. package/build/Controller.test.boc +0 -0
  70. package/build/Controller.test.compiled.json +1 -0
  71. package/build/Controller.test.fif +6400 -0
  72. package/build/Counter.boc +0 -0
  73. package/build/Counter.compiled.json +1 -0
  74. package/build/Counter.fif +4809 -0
  75. package/build/Counter.permissions.test.boc +0 -0
  76. package/build/Counter.permissions.test.compiled.json +1 -0
  77. package/build/Counter.permissions.test.fif +7106 -0
  78. package/build/Counter.setters.test.boc +0 -0
  79. package/build/Counter.setters.test.compiled.json +1 -0
  80. package/build/Counter.setters.test.fif +7083 -0
  81. package/build/Counter.test.boc +0 -0
  82. package/build/Counter.test.compiled.json +1 -0
  83. package/build/Counter.test.fif +7540 -0
  84. package/build/Dvn.boc +0 -0
  85. package/build/Dvn.compiled.json +1 -0
  86. package/build/Dvn.fif +2923 -0
  87. package/build/Dvn.test.boc +0 -0
  88. package/build/Dvn.test.compiled.json +1 -0
  89. package/build/Dvn.test.fif +5753 -0
  90. package/build/Endpoint.boc +0 -0
  91. package/build/Endpoint.compiled.json +1 -0
  92. package/build/Endpoint.fif +3694 -0
  93. package/build/Endpoint.permissions.test.boc +0 -0
  94. package/build/Endpoint.permissions.test.compiled.json +1 -0
  95. package/build/Endpoint.permissions.test.fif +6211 -0
  96. package/build/Endpoint.test.boc +0 -0
  97. package/build/Endpoint.test.compiled.json +1 -0
  98. package/build/Endpoint.test.fif +6899 -0
  99. package/build/EndpointSetEpConfigDefaults.test.boc +0 -0
  100. package/build/EndpointSetEpConfigDefaults.test.compiled.json +1 -0
  101. package/build/EndpointSetEpConfigDefaults.test.fif +6529 -0
  102. package/build/Executor.boc +0 -0
  103. package/build/Executor.compiled.json +1 -0
  104. package/build/Executor.fif +2731 -0
  105. package/build/Executor.test.boc +0 -0
  106. package/build/Executor.test.compiled.json +1 -0
  107. package/build/Executor.test.fif +5822 -0
  108. package/build/LzClasses.test.boc +0 -0
  109. package/build/LzClasses.test.compiled.json +1 -0
  110. package/build/LzClasses.test.fif +4457 -0
  111. package/build/LzUtil.test.boc +0 -0
  112. package/build/LzUtil.test.compiled.json +1 -0
  113. package/build/LzUtil.test.fif +1831 -0
  114. package/build/MsgData.test.boc +0 -0
  115. package/build/MsgData.test.compiled.json +1 -0
  116. package/build/MsgData.test.fif +4318 -0
  117. package/build/MsglibPacketCodec.test.boc +0 -0
  118. package/build/MsglibPacketCodec.test.compiled.json +1 -0
  119. package/build/MsglibPacketCodec.test.fif +4851 -0
  120. package/build/MultiSig.boc +0 -0
  121. package/build/MultiSig.compiled.json +1 -0
  122. package/build/MultiSig.fif +727 -0
  123. package/build/MultiSigOrder.boc +0 -0
  124. package/build/MultiSigOrder.compiled.json +1 -0
  125. package/build/MultiSigOrder.fif +650 -0
  126. package/build/PipelinedOutOfOrder.test.boc +0 -0
  127. package/build/PipelinedOutOfOrder.test.compiled.json +1 -0
  128. package/build/PipelinedOutOfOrder.test.fif +2188 -0
  129. package/build/SmlConnection.boc +0 -0
  130. package/build/SmlConnection.compiled.json +1 -0
  131. package/build/SmlConnection.fif +2517 -0
  132. package/build/SmlConnection.permissions.test.boc +0 -0
  133. package/build/SmlConnection.permissions.test.compiled.json +1 -0
  134. package/build/SmlConnection.permissions.test.fif +5497 -0
  135. package/build/SmlConnection.test.boc +0 -0
  136. package/build/SmlConnection.test.compiled.json +1 -0
  137. package/build/SmlConnection.test.fif +5494 -0
  138. package/build/SmlManager.boc +0 -0
  139. package/build/SmlManager.compiled.json +1 -0
  140. package/build/SmlManager.fif +3904 -0
  141. package/build/SmlManager.permissions.test.boc +0 -0
  142. package/build/SmlManager.permissions.test.compiled.json +1 -0
  143. package/build/SmlManager.permissions.test.fif +6018 -0
  144. package/build/SmlManager.test.boc +0 -0
  145. package/build/SmlManager.test.compiled.json +1 -0
  146. package/build/SmlManager.test.fif +6047 -0
  147. package/build/Uln.boc +0 -0
  148. package/build/Uln.compiled.json +1 -0
  149. package/build/Uln.fif +4841 -0
  150. package/build/Uln.test.boc +0 -0
  151. package/build/Uln.test.compiled.json +1 -0
  152. package/build/Uln.test.fif +7077 -0
  153. package/build/UlnManager.boc +0 -0
  154. package/build/UlnManager.compiled.json +1 -0
  155. package/build/UlnManager.fif +3851 -0
  156. package/build/UlnManager.test.boc +0 -0
  157. package/build/UlnManager.test.compiled.json +1 -0
  158. package/build/UlnManager.test.fif +6571 -0
  159. package/build/UlnReceiveConfig.test.boc +0 -0
  160. package/build/UlnReceiveConfig.test.compiled.json +1 -0
  161. package/build/UlnReceiveConfig.test.fif +4413 -0
  162. package/build/UlnSend.test.boc +0 -0
  163. package/build/UlnSend.test.compiled.json +1 -0
  164. package/build/UlnSend.test.fif +6576 -0
  165. package/build/UlnSendConfig.test.boc +0 -0
  166. package/build/UlnSendConfig.test.compiled.json +1 -0
  167. package/build/UlnSendConfig.test.fif +4431 -0
  168. package/build/UlnSendWorkerFactory.test.boc +0 -0
  169. package/build/UlnSendWorkerFactory.test.compiled.json +1 -0
  170. package/build/UlnSendWorkerFactory.test.fif +6683 -0
  171. package/build/UlnUtil.test.boc +0 -0
  172. package/build/UlnUtil.test.compiled.json +1 -0
  173. package/build/UlnUtil.test.fif +5873 -0
  174. package/build/WorkerCore.test.boc +0 -0
  175. package/build/WorkerCore.test.compiled.json +1 -0
  176. package/build/WorkerCore.test.fif +5630 -0
  177. package/build/ZroMinter.boc +0 -0
  178. package/build/ZroMinter.compiled.json +1 -0
  179. package/build/ZroMinter.fif +2300 -0
  180. package/build/ZroWallet.boc +0 -0
  181. package/build/ZroWallet.compiled.json +1 -0
  182. package/build/ZroWallet.fif +2471 -0
  183. package/package.json +64 -0
  184. package/src/classes/lz/Attestation.fc +23 -0
  185. package/src/classes/lz/Config.fc +23 -0
  186. package/src/classes/lz/EpConfig.fc +91 -0
  187. package/src/classes/lz/MsglibInfo.fc +31 -0
  188. package/src/classes/lz/Packet.fc +202 -0
  189. package/src/classes/lz/Path.fc +56 -0
  190. package/src/classes/lz/ReceiveEpConfig.fc +24 -0
  191. package/src/classes/lz/SendEpConfig.fc +18 -0
  192. package/src/classes/lz/SmlJobAssigned.fc +20 -0
  193. package/src/classes/lz/Worker.fc +32 -0
  194. package/src/classes/msgdata/AddMsglib.fc +18 -0
  195. package/src/classes/msgdata/Amount.fc +16 -0
  196. package/src/classes/msgdata/Bool.fc +16 -0
  197. package/src/classes/msgdata/ChannelNonceInfo.fc +18 -0
  198. package/src/classes/msgdata/ClaimUnaccountedPoolFunds.fc +0 -0
  199. package/src/classes/msgdata/CoinsAmount.fc +16 -0
  200. package/src/classes/msgdata/CounterIncrement.fc +24 -0
  201. package/src/classes/msgdata/Deploy.fc +20 -0
  202. package/src/classes/msgdata/ExtendedMd.fc +20 -0
  203. package/src/classes/msgdata/GetMsglibCallback.fc +18 -0
  204. package/src/classes/msgdata/InitEndpoint.fc +16 -0
  205. package/src/classes/msgdata/InitSmlConnection.fc +16 -0
  206. package/src/classes/msgdata/InitUlnConnection.fc +18 -0
  207. package/src/classes/msgdata/LzReceiveStatus.fc +58 -0
  208. package/src/classes/msgdata/LzSend.fc +58 -0
  209. package/src/classes/msgdata/MdAddress.fc +18 -0
  210. package/src/classes/msgdata/MdEid.fc +18 -0
  211. package/src/classes/msgdata/MdObj.fc +18 -0
  212. package/src/classes/msgdata/MessagingReceipt.fc +22 -0
  213. package/src/classes/msgdata/MsglibSendCallback.fc +113 -0
  214. package/src/classes/msgdata/Nonce.fc +16 -0
  215. package/src/classes/msgdata/OptionsExtended.fc +20 -0
  216. package/src/classes/msgdata/OptionsV1.fc +27 -0
  217. package/src/classes/msgdata/OptionsV2.fc +34 -0
  218. package/src/classes/msgdata/PacketId.fc +18 -0
  219. package/src/classes/msgdata/PacketSent.fc +39 -0
  220. package/src/classes/msgdata/SetAddress.fc +16 -0
  221. package/src/classes/msgdata/SetEpConfig.fc +33 -0
  222. package/src/classes/msgdata/SetPeer.fc +18 -0
  223. package/src/classes/msgdata/SetSmlManagerConfig.fc +18 -0
  224. package/src/funC++/abstract/contractMainAbstract.fc +3 -0
  225. package/src/funC++/abstract/handlerAbstract.fc +12 -0
  226. package/src/funC++/actions/call.fc +51 -0
  227. package/src/funC++/actions/deploy.fc +118 -0
  228. package/src/funC++/actions/destroy.fc +28 -0
  229. package/src/funC++/actions/dispatch.fc +57 -0
  230. package/src/funC++/actions/event.fc +69 -0
  231. package/src/funC++/actions/payment.fc +52 -0
  232. package/src/funC++/actions/sendJettons.fc +76 -0
  233. package/src/funC++/actions/utils.fc +49 -0
  234. package/src/funC++/baseInterface.fc +16 -0
  235. package/src/funC++/classlib.fc +819 -0
  236. package/src/funC++/constants.fc +64 -0
  237. package/src/funC++/contractMain.fc +84 -0
  238. package/src/funC++/dataStructures/DeterministicInsertionCircularQueue.fc +155 -0
  239. package/src/funC++/dataStructures/PipelinedOutOfOrder.fc +93 -0
  240. package/src/funC++/handlerCore.fc +30 -0
  241. package/src/funC++/stdlib.fc +625 -0
  242. package/src/funC++/stringlib.fc +75 -0
  243. package/src/funC++/txnContext.fc +126 -0
  244. package/src/funC++/utils.fc +119 -0
  245. package/src/jettons/zro/minter.fc +120 -0
  246. package/src/jettons/zro/op-codes.fc +10 -0
  247. package/src/jettons/zro/params.fc +18 -0
  248. package/src/jettons/zro/utils.fc +33 -0
  249. package/src/jettons/zro/wallet.fc +261 -0
  250. package/tests/baseContractTest.fc +192 -0
  251. package/tests/testMain.fc +135 -0
@@ -0,0 +1,819 @@
1
+ #include "utils.fc";
2
+ #include "constants.fc";
3
+ #include "stdlib.fc";
4
+ #include "stringlib.fc";
5
+
6
+ ;; Types for storage abstraction
7
+ const int cl::t::bool = 0;
8
+ const int cl::t::uint8 = 3;
9
+ const int cl::t::uint16 = 4;
10
+ const int cl::t::uint32 = 5;
11
+ const int cl::t::uint64 = 6;
12
+ const int cl::t::coins = 7; ;; fixed-width uint128, because we are civilized people
13
+ const int cl::t::uint256 = 8;
14
+ const int cl::t::address = cl::t::uint256;
15
+ const int cl::t::cellRef = 9;
16
+ const int cl::t::dict256 = cl::t::cellRef;
17
+ const int cl::t::objRef = cl::t::cellRef;
18
+ const int INVALID_TYPE = 13;
19
+
20
+ const int DICT256_KEYLEN = 256;
21
+
22
+ const int cl::NULL_CLASS_NAME = "NULL"u;
23
+
24
+ const int cl::ERROR::INVALID_CLASS = "cl::ERROR::INVALID_CLASS"c & ERRORCODE_MASK;
25
+
26
+ const int DEBUG = 0;
27
+
28
+ const int MAX_NAME_LEN = 10; ;; each name can be up to 10 characters long
29
+ const int _NAME_WIDTH = 8 * MAX_NAME_LEN; ;; convert to bits
30
+ const int _BASIC_HEADER_WIDTH = _NAME_WIDTH;
31
+ const int MAX_NAME_INTLEN = (1 << (8 * MAX_NAME_LEN)) - 1;
32
+
33
+ const int _FIELD_TYPE_WIDTH+_CELL_ID_WIDTH = 6; ;; support up to 16 types
34
+
35
+ const int _FIELD_TYPE_WIDTH = 4; ;; support up to 16 types
36
+ const int _CELL_ID_WIDTH = 2; ;; the classlib backend supports up to 4 inner cells including root
37
+ const int _DATA_OFFSET_WIDTH = 10; ;; 1023 bits per cell = 2**10 - 1
38
+ const int _REF_OFFSET_WIDTH = 2; ;; each cell can have up to 4 refs
39
+ const int _FIELD_INFO_WIDTH = _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH + _DATA_OFFSET_WIDTH + _REF_OFFSET_WIDTH;
40
+ const int _MAX_CLASS_FIELDS = 15; ;; reserve 0xff for the "invalid" object field name
41
+ const int INVALID_CLASS_MEMBER = 16;
42
+ const int _HEADER_WIDTH = _BASIC_HEADER_WIDTH + _MAX_CLASS_FIELDS * _FIELD_INFO_WIDTH;
43
+
44
+ ;; declarations require a tuple of the form [[ name, type, val ], ...]
45
+ const int FIELD_TYPE_IDX = 0;
46
+ const int FIELD_VAL_IDX = 1;
47
+
48
+ ;;; ====================== Address functions ======================
49
+ int basechainAddressStdToHashpart(slice full_address) inline {
50
+ (int wc, int hp) = parseStdAddress(full_address);
51
+ if (DEBUG) {
52
+ throw_unless(0, wc == BASECHAIN);
53
+ }
54
+ return hp;
55
+ }
56
+
57
+ slice hashpartToBasechainAddressStd(int hashpart) inline {
58
+ return begin_cell()
59
+ .store_uint(4, 3) ;; 0b100
60
+ .store_int(BASECHAIN, 8)
61
+ .store_uint(hashpart, 256)
62
+ .as_slice();
63
+ }
64
+
65
+ int getContractAddress() impure inline {
66
+ return my_address().preload_bits_offset(11, 256).preload_uint(256);
67
+ }
68
+
69
+ slice cl::objToSlice(cell $obj) inline method_id {
70
+ return $obj.begin_parse();
71
+ }
72
+
73
+ ;;; ====================== Class functions ======================
74
+ ;; returns type width in bits
75
+ int _getTypeWidth(int clType) inline {
76
+ if (clType <= cl::t::uint256) {
77
+ return 1 << clType; ;; type names are set up so this is true
78
+ }
79
+ ;; all other types are ref types with 0 data bits
80
+ return 0;
81
+ }
82
+
83
+ int cl::hash(cell $obj) impure inline {
84
+ return $obj.cell_hash();
85
+ }
86
+
87
+ int cl::isNull(cell $obj) impure inline {
88
+ return $obj.cell_is_empty();
89
+ }
90
+
91
+ ;; checks if a class lib object is flat, and contains no 'refs'
92
+ ;; null is considered 'flat'
93
+ int cl::noRefFields(cell $obj) {
94
+ slice headerSlice = $obj.begin_parse();
95
+ int numRefs = headerSlice.slice_refs();
96
+
97
+ if (numRefs == 0) {
98
+ return true;
99
+ } elseif (numRefs <= 2) {
100
+ ;; if there are refs, the struct is not flat
101
+ return false;
102
+ }
103
+
104
+ if (numRefs >= 3) {
105
+ if (
106
+ (headerSlice.preload_ref_at(0).cell_is_empty() == false)
107
+ | (headerSlice.preload_ref_at(1).cell_is_empty() == false)
108
+ | (headerSlice.preload_ref_at(2).begin_parse().slice_refs() != 0)
109
+ ) {
110
+ ;; if there is 1 structural node, that structural node must have 0 refs
111
+ return false;
112
+ }
113
+ }
114
+
115
+ if (numRefs >= 4) {
116
+ if (headerSlice.preload_ref_at(3).begin_parse().slice_refs() != 0) {
117
+ return false;
118
+ }
119
+ }
120
+
121
+ return true;
122
+ }
123
+
124
+ int cl::equalObjTypeShallow(cell $a, cell $b) {
125
+ slice aSlice = $a.begin_parse();
126
+ slice bSlice = $b.begin_parse();
127
+ int aRefs = aSlice.slice_refs();
128
+
129
+ if (
130
+ (aRefs != bSlice.slice_refs())
131
+ | (aSlice.slice_bits() != bSlice.slice_bits())
132
+ ) {
133
+ return false;
134
+ }
135
+
136
+ int refIndex = 2;
137
+ while (refIndex < aRefs) {
138
+ if (
139
+ (aSlice.preload_ref_at(refIndex).begin_parse().slice_refs() != bSlice.preload_ref_at(refIndex).begin_parse().slice_refs())
140
+ | (aSlice.preload_ref_at(refIndex).begin_parse().slice_bits() != bSlice.preload_ref_at(refIndex).begin_parse().slice_bits())
141
+ ) {
142
+ return false;
143
+ }
144
+ refIndex += 1;
145
+ }
146
+
147
+ return true;
148
+ }
149
+
150
+ () setContractStorage(cell $obj) impure inline {
151
+ set_data($obj);
152
+ }
153
+
154
+ cell getContractStorage() impure inline method_id {
155
+ return get_data();
156
+ }
157
+
158
+ int computeContractAddress(cell $storage, cell code) impure inline {
159
+ return begin_cell()
160
+ .store_uint(6, 5)
161
+ .store_ref(code)
162
+ .store_ref($storage)
163
+ .end_cell()
164
+ .cell_hash();
165
+ }
166
+
167
+ int cl::typeof(cell $obj) inline method_id {
168
+ if (cl::isNull($obj)) {
169
+ return cl::NULL_CLASS_NAME;
170
+ }
171
+ return $obj.begin_parse().preload_uint(_NAME_WIDTH);
172
+ }
173
+
174
+ cell cl::declare(int name, tuple fields) inline method_id {
175
+ tuple classBuilder = unsafeTuple([null(), begin_cell()]);
176
+
177
+ if (DEBUG) {
178
+ if (name > MAX_NAME_INTLEN) {
179
+ ~strdump("Class name too long! ".str::concat(str::asciiUint256ToStr(name)));
180
+ }
181
+ }
182
+
183
+ int num_fields = fields.tlen();
184
+ builder headerBuilder = begin_cell().store_uint(name, _NAME_WIDTH);
185
+
186
+ ;; Loop indices
187
+ int curDataCell = 1;
188
+ int curRefCell = 1;
189
+ ;; allow one direct ref in the root cell
190
+ int curCellMaxRefs = 2;
191
+ int curDataOffset = _HEADER_WIDTH;
192
+ int curRefOffset = 0;
193
+
194
+ int curField = 0;
195
+ while (curField < num_fields) {
196
+ ;; ======================
197
+ ;; loop management
198
+ tuple field = fields.tuple_at(curField);
199
+ int fieldType = field.int_at(FIELD_TYPE_IDX);
200
+ ;; ===================================
201
+ int fieldBits = _getTypeWidth(fieldType);
202
+ if ((curDataOffset + fieldBits) > MAX_CELL_BITS) {
203
+ ;; move to the next cell
204
+ curDataCell += 1;
205
+ curDataOffset = 0;
206
+ if (curDataCell >= classBuilder.tlen()) {
207
+ classBuilder = classBuilder.tpush(begin_cell());
208
+ }
209
+ }
210
+ if ((curRefOffset + 1) > curCellMaxRefs) {
211
+ ;; move to the next cell
212
+ curRefCell += 1;
213
+ curRefOffset = 0;
214
+ curCellMaxRefs = MAX_CELL_REFS;
215
+ if (curRefCell >= classBuilder.tlen()) {
216
+ classBuilder = classBuilder.tpush(begin_cell());
217
+ }
218
+ }
219
+
220
+ if (fieldType <= cl::t::address) {
221
+ classBuilder = classBuilder.tset(
222
+ curDataCell,
223
+ cast_to_builder(classBuilder.at(curDataCell))
224
+ .store_uint(abs(field.int_at(FIELD_VAL_IDX)), fieldBits)
225
+ );
226
+ } elseif (fieldType == cl::t::objRef) {
227
+ classBuilder = classBuilder.tset(
228
+ curRefCell,
229
+ cast_to_builder(classBuilder.at(curRefCell))
230
+ .store_ref(field.cell_at(FIELD_VAL_IDX))
231
+ );
232
+ } else {
233
+ cell field_val = field.cell_at(FIELD_VAL_IDX);
234
+ classBuilder = classBuilder.tset(curRefCell,
235
+ cast_to_builder(classBuilder.at(curRefCell))
236
+ .store_ref(field_val)
237
+ );
238
+ }
239
+
240
+ headerBuilder = headerBuilder
241
+ .store_uint(fieldType, _FIELD_TYPE_WIDTH);
242
+ if (fieldBits > 0) {
243
+ headerBuilder = headerBuilder
244
+ .store_uint(curDataCell == 1 ? 0 : curDataCell, _CELL_ID_WIDTH)
245
+ .store_uint(curDataOffset, _DATA_OFFSET_WIDTH)
246
+ .store_uint(3, _REF_OFFSET_WIDTH);
247
+ curDataOffset += fieldBits;
248
+ } else {
249
+ headerBuilder = headerBuilder
250
+ .store_uint(curRefCell == 1 ? 0 : curRefCell, _CELL_ID_WIDTH)
251
+ .store_uint(MAX_CELL_BITS, _DATA_OFFSET_WIDTH)
252
+ .store_uint(curRefOffset, _REF_OFFSET_WIDTH);
253
+ curRefOffset += 1;
254
+ }
255
+ curField += 1;
256
+ }
257
+
258
+
259
+ builder rootBuilder = classBuilder.at(1);
260
+ int numCells = classBuilder.tlen() - 1;
261
+ if (DEBUG) {
262
+ throw_if(cl::ERROR::INVALID_CLASS, numCells > 3);
263
+ }
264
+ if (numCells > 1) {
265
+ if (rootBuilder.builder_refs() == 0) {
266
+ rootBuilder = rootBuilder
267
+ .store_ref(empty_cell())
268
+ .store_ref(empty_cell());
269
+ } elseif (rootBuilder.builder_refs() == 1) {
270
+ rootBuilder = rootBuilder
271
+ .store_ref(empty_cell());
272
+ }
273
+ }
274
+
275
+ headerBuilder = headerBuilder
276
+ .store_ones(_HEADER_WIDTH - headerBuilder.builder_bits())
277
+ .store_builder(rootBuilder);
278
+
279
+ if (numCells == 1) {
280
+ return headerBuilder.end_cell();
281
+ }
282
+ if (numCells == 2) {
283
+ return headerBuilder
284
+ .store_ref(classBuilder.at(2).end_cell())
285
+ .end_cell();
286
+ }
287
+ return headerBuilder
288
+ .store_ref(classBuilder.at(2).end_cell())
289
+ .store_ref(classBuilder.at(3).end_cell())
290
+ .end_cell();
291
+ }
292
+
293
+ cell cl::nullObject() inline method_id {
294
+ return empty_cell();
295
+ }
296
+
297
+ ;;; ====================== Class Setter ======================
298
+ int cl::getFieldType::asm(slice self, int fieldInfoOffset ) asm """
299
+ // STACK [fieldInfoOffset, headerSlice]
300
+ 4 PUSHINT // STACK [_FIELD_TYPE_WIDTH, fieldInfoOffset, headerSlice]
301
+ SDSUBSTR // STACK [substring]
302
+ 4 PLDU // STACK [2BitUnsignInt]
303
+ """;
304
+
305
+ int cl::getFieldCellIndex::asm(slice self, int fieldInfoOffset ) asm """
306
+ 4 ADDCONST // STACK [fieldInfoOffset + _FIELD_TYPE_WIDTH, headerSlice]
307
+ 2 PUSHINT // STACK [_CELL_ID_WIDTH, fieldInfoOffset + _FIELD_TYPE_WIDTH, headerSlice]
308
+ SDSUBSTR // STACK [substring]
309
+ 2 PLDU // STACK [2BitUnsignInt]
310
+ """;
311
+
312
+ int cl::getFieldOffset::asm(slice self, int fieldInfoOffset ) asm """
313
+ 6 ADDCONST // STACK [fieldInfoOffset + _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH, headerSlice]
314
+ 10 PUSHINT // STACK [_DATA_OFFSET_WIDTH, fieldInfoOffset +_FIELD_TYPE_WIDTH + _CELL_ID_WIDTH, headerSlice]
315
+ SDSUBSTR // STACK [substring]
316
+ 10 PLDU // STACK [10BitUnsignInt]
317
+ """;
318
+
319
+ int cl::getFieldCellOffset::asm(slice self, int fieldInfoOffset ) asm """
320
+ 16 ADDCONST // STACK [fieldInfoOffset + _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH + _DATA_OFFSET_WIDTH, headerSlice]
321
+ 2 PUSHINT // STACK [_REF_OFFSET_WIDTH, fieldInfoOffset + _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH + _DATA_OFFSET_WIDTH headerSlice]
322
+ SDSUBSTR // STACK [substring]
323
+ 2 PLDU // STACK [10BitUnsignInt]
324
+ """;
325
+
326
+ int cl::preload_bits_offset_3::asm(int width1, slice self, int fieldOffset, int width2 ) asm """
327
+ SDSUBSTR // STACK [substring]
328
+ s1 XCHG0
329
+ PLDUX // STACK [10BitUnsignInt] (CC +1 )
330
+ """;
331
+
332
+ forall X -> cell cl::set(cell $self, int fieldName, X val) inline method_id {
333
+ slice headerSlice = $self.begin_parse();
334
+ int fieldInfoOffset = _BASIC_HEADER_WIDTH + (fieldName * _FIELD_INFO_WIDTH);
335
+ int fieldCellIndex = headerSlice.cl::getFieldCellIndex::asm(fieldInfoOffset);
336
+ int fieldType = headerSlice.cl::getFieldType::asm(fieldInfoOffset);
337
+ int fieldOffset = headerSlice.cl::getFieldOffset::asm(fieldInfoOffset);
338
+ int fieldRefsOffset = headerSlice.cl::getFieldCellOffset::asm(fieldInfoOffset );
339
+
340
+ if (DEBUG) {
341
+ throwErrorUnless(fieldType < INVALID_TYPE, "Type does not exist");
342
+ }
343
+
344
+ int fieldWidth = _getTypeWidth(fieldType);
345
+ slice victim = fieldCellIndex == 0
346
+ ? headerSlice
347
+ : headerSlice.preload_ref_at(fieldCellIndex).begin_parse();
348
+ if (fieldWidth != 0) {
349
+ fieldRefsOffset = MAX_CELL_REFS;
350
+ }
351
+
352
+ builder replacement = begin_cell()
353
+ .store_slice(
354
+ victim.scutfirst(
355
+ min(victim.slice_bits(), fieldOffset),
356
+ min(fieldRefsOffset, victim.slice_refs())
357
+ )
358
+ );
359
+
360
+ if (fieldType == cl::t::cellRef) {
361
+ replacement = replacement
362
+ .store_ref(val.cast_to_cell())
363
+ .store_slice(victim.scutlast(0, victim.slice_refs() - fieldRefsOffset - 1));
364
+ } elseif (fieldType == cl::t::objRef) {
365
+ replacement = replacement
366
+ .store_ref(val.cast_to_cell())
367
+ .store_slice(victim.scutlast(0, victim.slice_refs() - fieldRefsOffset - 1));
368
+ } else { ;; numeric type
369
+ replacement = replacement
370
+ .store_uint(abs(val.cast_to_int()), fieldWidth)
371
+ .store_slice(victim.sskipfirst(fieldOffset + fieldWidth, victim.slice_refs()));
372
+ }
373
+
374
+ if (fieldCellIndex > 0) {
375
+ ;; link the replacement into the root cell
376
+ return begin_cell()
377
+ .store_slice(headerSlice.scutfirst(headerSlice.slice_bits(), fieldCellIndex))
378
+ .store_ref(replacement.end_cell())
379
+ .store_slice(headerSlice.scutlast(0, headerSlice.slice_refs() - fieldCellIndex - 1))
380
+ .end_cell();
381
+ }
382
+ return replacement.end_cell();
383
+ }
384
+ ;;; ====================== Class Getters ======================
385
+
386
+ const int _NAME_WIDTH = 8 * MAX_NAME_LEN; ;; convert to bits
387
+ const int _BASIC_HEADER_WIDTH = _NAME_WIDTH;
388
+ const int MAX_NAME_INTLEN = (1 << (8 * MAX_NAME_LEN)) - 1;
389
+
390
+ const int _FIELD_TYPE_WIDTH+_CELL_ID_WIDTH = 6; ;; support up to 16 types
391
+
392
+ const int _FIELD_TYPE_WIDTH = 4; ;; support up to 16 types
393
+ const int _CELL_ID_WIDTH = 2; ;; the classlib backend supports up to 4 inner cells including root
394
+ const int _DATA_OFFSET_WIDTH = 10; ;; 1023 bits per cell = 2**10 - 1
395
+
396
+ ;; int cl::get<uint>::asm_t( int width, int fieldName, tuple self) asm """
397
+ ;; // DUMPSTK // STACK [s, fieldName, width]
398
+ ;; 0 INDEX // cell cell_at(tuple t, int index) => STACK [cellResult, fieldName, width]
399
+ ;; CTOS // slice begin_parse(cell c) => STACK [sliceResult, fieldName, width]
400
+ ;; s1 XCHG0 // STACK [fieldName, sliceResult, width]
401
+ ;; 18 MULCONST // STACK [_FIELD_INFO_WIDTH*fieldName, sliceResult, width]
402
+ ;; 84 ADDCONST // STACK [_BASIC_HEADER_WIDTH + _FIELD_TYPE_WIDTH + (_FIELD_INFO_WIDTH*fieldName) = fieldInfoOffset, mulRes, sliceResult, width]
403
+ ;; s1 s1 s1 XCHG3 // STACK [width, fieldInfoOffset, sliceResult]
404
+ ;; SDSUBSTR // STACK [preloadBitsOffsetResult]
405
+ ;; 10 PLDU // STACK [fieldCellIndex]
406
+ ;; """;
407
+
408
+ int cl::get<uint>(cell $self, int fieldName, int width) inline method_id {
409
+ slice headerSlice = $self.begin_parse();
410
+
411
+ int fieldInfoOffset = _BASIC_HEADER_WIDTH + (fieldName * _FIELD_INFO_WIDTH);
412
+ int fieldCellIndex = headerSlice.cl::getFieldCellIndex::asm(fieldInfoOffset);
413
+ int fieldOffset = headerSlice.cl::getFieldOffset::asm(fieldInfoOffset);
414
+
415
+ if (DEBUG) {
416
+ int fieldType = headerSlice
417
+ .preload_bits_offset(
418
+ fieldInfoOffset,
419
+ _FIELD_TYPE_WIDTH
420
+ )
421
+ .preload_uint(_FIELD_TYPE_WIDTH);
422
+ int expected_field_width = _getTypeWidth(fieldType);
423
+ throw_unless(0, expected_field_width == width);
424
+ }
425
+
426
+ if (fieldCellIndex == 0) {
427
+ return cl::preload_bits_offset_3::asm(width, headerSlice, fieldOffset, width);
428
+ }
429
+ else {
430
+ return cl::preload_bits_offset_3::asm( width, headerSlice.preload_ref_at(fieldCellIndex).begin_parse(), fieldOffset, width);
431
+ }
432
+ }
433
+
434
+ cell cl::get<cellRef>(cell $self, int fieldName) inline method_id {
435
+ slice headerSlice = $self.begin_parse();
436
+ int fieldInfoOffset = _BASIC_HEADER_WIDTH + (fieldName * _FIELD_INFO_WIDTH);
437
+ int fieldCellIndex = headerSlice.cl::getFieldCellIndex::asm(
438
+ fieldInfoOffset);
439
+ int fieldRefIdx = headerSlice
440
+ .cl::getFieldCellOffset::asm(
441
+ fieldInfoOffset);
442
+
443
+ if (DEBUG) {
444
+ int fieldType = headerSlice
445
+ .preload_bits_offset(
446
+ fieldInfoOffset,
447
+ _FIELD_TYPE_WIDTH
448
+ )
449
+ .preload_uint(_FIELD_TYPE_WIDTH);
450
+ int expected_field_width = _getTypeWidth(fieldType);
451
+ throw_unless(0, expected_field_width == 0);
452
+ }
453
+
454
+ return fieldCellIndex == 0
455
+ ? headerSlice.preload_ref_at(fieldRefIdx)
456
+ : (headerSlice
457
+ .preload_ref_at(fieldCellIndex)
458
+ .begin_parse()
459
+ .preload_ref_at(fieldRefIdx)
460
+ );
461
+ }
462
+
463
+ cell cl::getWithCell<cellRef>(cell $self, int fieldName) inline method_id {
464
+ return $self.cl::get<cellRef>(fieldName);
465
+ }
466
+
467
+ cell cl::get<objRef>(cell $self, int fieldName) inline method_id {
468
+ return cl::get<cellRef>($self, fieldName);
469
+ }
470
+
471
+ int cl::get<uint8>(cell $self, int fieldName) inline method_id {
472
+ return $self.cl::get<uint>(fieldName, 8);
473
+ }
474
+
475
+ int cl::get<uint16>(cell $self, int fieldName) inline method_id {
476
+ return $self.cl::get<uint>(fieldName, 16);
477
+ }
478
+
479
+ int cl::get<uint32>(cell $self, int fieldName) inline method_id {
480
+ return $self.cl::get<uint>(fieldName, 32);
481
+ }
482
+
483
+ int cl::get<uint64>(cell $self, int fieldName) inline method_id {
484
+ return $self.cl::get<uint>(fieldName, 64);
485
+ }
486
+
487
+ int cl::get<coins>(cell $self, int fieldName) inline method_id {
488
+ return $self.cl::get<uint>(fieldName, 128);
489
+ }
490
+
491
+ int cl::get<uint256>(cell $self, int fieldName) inline method_id {
492
+ return $self.cl::get<uint>(fieldName, 256);
493
+ }
494
+
495
+ slice cl::get<std_address>(cell $self, int fieldName) inline method_id {
496
+ return hashpartToBasechainAddressStd(
497
+ $self.cl::get<uint>(fieldName, 256)
498
+ );
499
+ }
500
+
501
+ int cl::get<bool>(cell $self, int fieldName) inline method_id {
502
+ return $self.cl::get<uint>(fieldName, 1) != 0;
503
+ }
504
+
505
+ cell cl::get<dict256>(cell $self, int fieldName) inline method_id {
506
+ return $self.cl::get<cellRef>(fieldName);
507
+ }
508
+
509
+ int cl::get<address>(cell $self, int fieldName) inline method_id {
510
+ return $self.cl::get<uint>(fieldName, 256);
511
+ }
512
+
513
+ ;;; =============== DEBUG / CONVENIENCE FUNCTIONS =================
514
+ int typeofField(cell $self, int fieldName) inline {
515
+ slice headerSlice = $self.begin_parse();
516
+ int fieldInfoOffset = _BASIC_HEADER_WIDTH + (fieldName * _FIELD_INFO_WIDTH);
517
+ return headerSlice
518
+ .preload_bits_offset(
519
+ fieldInfoOffset,
520
+ _FIELD_TYPE_WIDTH
521
+ )
522
+ .preload_uint(_FIELD_TYPE_WIDTH);
523
+ }
524
+
525
+ ;; returns -1 (true) if equal, otherwise the index of the first field that differs
526
+ int compareObjectFields(cell $lhs, cell $rhs) impure inline {
527
+ int malformed = cl::typeof($lhs) != cl::typeof($rhs);
528
+ if (malformed) {
529
+ return INVALID_CLASS_MEMBER;
530
+ }
531
+ if (cl::typeof($lhs) == cl::NULL_CLASS_NAME) {
532
+ return -1;
533
+ }
534
+ int fieldIndex = 0;
535
+ while (fieldIndex < INVALID_CLASS_MEMBER) {
536
+ int curFieldType = $lhs.typeofField(fieldIndex);
537
+ if (curFieldType == cl::t::cellRef) {
538
+ malformed = $lhs.cl::get<objRef>(fieldIndex).cl::hash() != $rhs.cl::get<objRef>(fieldIndex).cl::hash();
539
+ if (malformed) {
540
+ ~dump($lhs.cl::get<objRef>(fieldIndex).cell_hash());
541
+ ~dump($rhs.cl::get<objRef>(fieldIndex).cell_hash());
542
+ }
543
+ } elseif (curFieldType <= cl::t::uint256) {
544
+ int cur_field_width = _getTypeWidth(curFieldType);
545
+ malformed = $lhs.cl::get<uint>(fieldIndex, cur_field_width) != $rhs.cl::get<uint>(fieldIndex, cur_field_width);
546
+ if (malformed) {
547
+ str::console::log<int>("lhs: ", $lhs.cl::get<uint>(fieldIndex, cur_field_width));
548
+ str::console::log<int>("rhs: ", $rhs.cl::get<uint>(fieldIndex, cur_field_width));
549
+ }
550
+ } else {
551
+ fieldIndex = INVALID_CLASS_MEMBER;
552
+ }
553
+ if (malformed) {
554
+ str::console::log<int>("Malformed field: ", fieldIndex);
555
+ return fieldIndex;
556
+ }
557
+ fieldIndex += 1;
558
+ }
559
+ return -1;
560
+ }
561
+
562
+ int objectsAreEqual(cell $lhs, cell $rhs) impure inline {
563
+ return compareObjectFields($lhs, $rhs) == -1;
564
+ }
565
+
566
+ slice _typeToStr(int fieldType) {
567
+ if (fieldType == cl::t::uint8) { return "uint8"; }
568
+ elseif (fieldType == cl::t::uint16) { return "uint16"; }
569
+ elseif (fieldType == cl::t::uint32) { return "uint32"; }
570
+ elseif (fieldType == cl::t::uint64) { return "uint64"; }
571
+ elseif (fieldType == cl::t::uint256) { return "uint256"; }
572
+ elseif (fieldType == cl::t::coins) { return "coins"; }
573
+ elseif (fieldType == cl::t::address) { return "address"; }
574
+ elseif (fieldType == cl::t::dict256) { return "dict256"; }
575
+ elseif (fieldType == cl::t::objRef) { return "objRef"; }
576
+ elseif (fieldType == cl::t::cellRef) { return "cellRef"; }
577
+ elseif (fieldType == cl::t::bool) { return "bool"; }
578
+ else { return "unknown"; }
579
+ }
580
+
581
+ () printField(cell $obj, int fieldName) impure inline {
582
+ slice headerSlice = $obj.begin_parse();
583
+ int fieldType = typeofField($obj, fieldName);
584
+ int fieldInfoOffset = _BASIC_HEADER_WIDTH + (fieldName * _FIELD_INFO_WIDTH);
585
+ int fieldCellIndex = headerSlice
586
+ .preload_bits_offset(
587
+ fieldInfoOffset + _FIELD_TYPE_WIDTH,
588
+ _CELL_ID_WIDTH
589
+ )
590
+ .preload_uint(_CELL_ID_WIDTH);
591
+ int fieldRefIdx = headerSlice
592
+ .preload_bits_offset(
593
+ fieldInfoOffset + _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH + _DATA_OFFSET_WIDTH,
594
+ _REF_OFFSET_WIDTH
595
+ )
596
+ .preload_uint(_REF_OFFSET_WIDTH);
597
+
598
+ int fieldBits = _getTypeWidth(fieldType);
599
+ int fieldOffset = headerSlice
600
+ .preload_bits_offset(
601
+ fieldInfoOffset + _FIELD_TYPE_WIDTH + _CELL_ID_WIDTH,
602
+ _DATA_OFFSET_WIDTH
603
+ )
604
+ .preload_uint(_DATA_OFFSET_WIDTH);
605
+
606
+ slice toPrint = _typeToStr(fieldType)
607
+ .str::concat(" ")
608
+ .str::concatInt(fieldName)
609
+ .str::concat(" at c")
610
+ .str::concatInt(fieldCellIndex);
611
+ if (fieldBits > 0) {
612
+ toPrint = toPrint.str::concat(".b").str::concatInt(fieldOffset);
613
+ } else {
614
+ toPrint = toPrint.str::concat(".r").str::concatInt(fieldRefIdx);
615
+ }
616
+ if (fieldType <= cl::t::uint256) {
617
+ ~strdump(
618
+ toPrint
619
+ .str::concat(" = ")
620
+ .str::concatInt($obj.cl::get<uint>(fieldName, fieldBits))
621
+ );
622
+ } elseif (fieldType == cl::t::objRef) {
623
+ ~strdump(toPrint
624
+ .str::concat(" hash = ")
625
+ .str::concatInt($obj.cl::get<objRef>(fieldName).cl::hash())
626
+ );
627
+ } else {
628
+ ~strdump(toPrint
629
+ .str::concat(" hash = ")
630
+ .str::concatInt($obj.cl::get<cellRef>(fieldName).cell_hash())
631
+ );
632
+ }
633
+ }
634
+
635
+ ;;; ====================== Dictionary functions ======================
636
+
637
+ slice uint256ToSlice(int val) inline method_id {
638
+ return begin_cell().store_uint256(val).as_slice();
639
+ }
640
+
641
+ int sliceToUint256(slice s) inline method_id {
642
+ return s.preload_uint(256);
643
+ }
644
+
645
+ ;; override the insane behavior of TON to optimize out empty dictionaries
646
+ ;; into a single bit
647
+ cell cl::dict256::New() inline method_id {
648
+ return empty_cell();
649
+ }
650
+
651
+ (slice, int) cl::dict256::get(cell dict, int key) inline method_id {
652
+ if (dict.cell_is_empty()) {
653
+ return new_dict().udict_get?(DICT256_KEYLEN, key);
654
+ }
655
+ return dict.udict_get?(DICT256_KEYLEN, key);
656
+ }
657
+
658
+ (int, int) cl::dict256::get<uint256>(cell dict, int key) inline method_id {
659
+ (slice val, int exists) = cl::dict256::get(dict, key);
660
+ if (exists) {
661
+ return (sliceToUint256(val), true);
662
+ }
663
+ return (0, false);
664
+ }
665
+
666
+ (cell, int) cl::dict256::get<cellRef>(cell dict, int key) inline method_id {
667
+ if (dict.cell_is_empty()) {
668
+ return (empty_cell(), false);
669
+ }
670
+ return dict.udict_get_ref?(DICT256_KEYLEN, key);
671
+ }
672
+
673
+ cell cl::dict256::setRef(cell dict, int key, cell val) inline method_id {
674
+ if (dict.cell_is_empty()) {
675
+ return new_dict().udict_set_ref(
676
+ DICT256_KEYLEN,
677
+ key,
678
+ val.cast_to_cell()
679
+ );
680
+ }
681
+ return dict.udict_set_ref(DICT256_KEYLEN, key, val.cast_to_cell());
682
+ }
683
+ forall X -> cell cl::dict256::set(cell dict, int key, X val) inline {
684
+ slice _val = val.is_slice() ? val.cast_to_slice() : uint256ToSlice(val.cast_to_int());
685
+ if (dict.cell_is_empty()) {
686
+ return new_dict().udict_set(DICT256_KEYLEN, key, _val);
687
+ }
688
+ return dict.udict_set(DICT256_KEYLEN, key, _val);
689
+ }
690
+
691
+ cell cl::dict256::delete(cell dict, int key) {
692
+ if (dict.cell_is_empty()) {
693
+ return dict;
694
+ }
695
+ (cell modified_dict, _) = dict.udict_delete?(DICT256_KEYLEN, key);
696
+ return modified_dict.is_cell() ? modified_dict : cl::dict256::New();
697
+ }
698
+
699
+ ;;; ====================== Dictionary Iterators ======================
700
+ ;; returns key, val, and key == -1 if there is no next (or min) element
701
+ ;; if the val exists, it is returned
702
+ ;; if a val does not exist, null() is returned
703
+
704
+ (int, slice) cl::dict256::getMin<slice>(cell dict256) {
705
+ if (dict256.cell_is_empty()) {
706
+ return (-1, null());
707
+ }
708
+ (int key, slice val, int exists) = dict256.udict_get_min?(DICT256_KEYLEN);
709
+ if (exists) {
710
+ return (key, val);
711
+ }
712
+ return (-1, null());
713
+ }
714
+
715
+ (int, int) cl::dict256::getMin<uint256>(cell dict256) {
716
+ if (dict256.cell_is_empty()) {
717
+ return (-1, null());
718
+ }
719
+ (int key, slice val, int exists) = dict256.udict_get_min?(DICT256_KEYLEN);
720
+ if (exists) {
721
+ return (key, val.preload_uint(256));
722
+ }
723
+ return (-1, null());
724
+ }
725
+
726
+ (int, cell) cl::dict256::getMin<cellRef>(cell dict256) {
727
+ if (dict256.cell_is_empty()) {
728
+ return (-1, null());
729
+ }
730
+ (int key, cell val, int exists) = dict256.udict_get_min_ref?(DICT256_KEYLEN);
731
+ if (exists) {
732
+ return (key, val);
733
+ }
734
+ return (-1, null());
735
+ }
736
+
737
+ (int, slice) cl::dict256::getNext<slice>(cell dict256, int pivot) {
738
+ if (dict256.cell_is_empty()) {
739
+ return (-1, null());
740
+ }
741
+ (int key, slice val, int exists) = dict256.udict_get_next?(DICT256_KEYLEN, pivot);
742
+ if (exists) {
743
+ return (key, val);
744
+ }
745
+ return (-1, null());
746
+ }
747
+
748
+ (int, int) cl::dict256::getNext<uint256>(cell dict256, int pivot) {
749
+ if (dict256.cell_is_empty()) {
750
+ return (-1, null());
751
+ }
752
+ (int key, slice val, int exists) = dict256.udict_get_next?(DICT256_KEYLEN, pivot);
753
+ if (exists) {
754
+ return (key, val.preload_uint(256));
755
+ }
756
+ return (-1, null());
757
+ }
758
+
759
+ (int, cell) cl::dict256::getNext<cellRef>(cell dict256, int pivot) {
760
+ if (dict256.cell_is_empty()) {
761
+ return (-1, null());
762
+ }
763
+ (int key, slice val, int exists) = dict256.udict_get_next?(DICT256_KEYLEN, pivot);
764
+ if (exists) {
765
+ return (key, val.preload_first_ref());
766
+ }
767
+ return (-1, null());
768
+ }
769
+
770
+ int cl::dict256::size(cell dict) inline {
771
+ int count = 0;
772
+ (int pivot, _) = dict.cl::dict256::getMin<slice>();
773
+ while (pivot >= 0) {
774
+ (pivot, _) = dict.cl::dict256::getNext<slice>(pivot);
775
+ count = count + 1;
776
+ }
777
+ return count;
778
+ }
779
+
780
+ ;;; ====================== Nested Dict Helpers ======================
781
+
782
+ forall X -> cell cl::nestedDict256::set(cell $self, int fieldName, int key, X val) inline method_id {
783
+ return $self.cl::set(
784
+ fieldName,
785
+ $self
786
+ .cl::get<dict256>(fieldName)
787
+ .cl::dict256::set(key, val)
788
+ );
789
+ }
790
+
791
+ cell cl::nestedDict256::setRef(cell $self, int fieldName, int key, cell val) inline method_id {
792
+ return $self.cl::set(
793
+ fieldName,
794
+ $self.cl::get<dict256>(fieldName).cl::dict256::setRef(key, val)
795
+ );
796
+ }
797
+
798
+ cell cl::nestedDict256::delete(cell $self, int fieldName, int key) inline method_id {
799
+ return $self.cl::set(
800
+ fieldName,
801
+ $self.cl::get<dict256>(fieldName).cl::dict256::delete(key)
802
+ );
803
+ }
804
+
805
+ (int, int) cl::nestedDict256::get<uint256>(cell $self, int fieldName, int key) inline method_id {
806
+ return $self.cl::get<dict256>(fieldName).cl::dict256::get<uint256>(key);
807
+ }
808
+
809
+ (slice, int) cl::nestedDict256::get<slice>(cell $self, int fieldName, int key) inline method_id {
810
+ return $self.cl::get<dict256>(fieldName).cl::dict256::get(key);
811
+ }
812
+
813
+ (cell, int) cl::nestedDict256::get<cellRef>(cell $self, int fieldName, int key) inline method_id {
814
+ (slice s, int exists) = $self.cl::get<dict256>(fieldName).cl::dict256::get(key);
815
+ if (exists) {
816
+ return (s.preload_first_ref(), exists);
817
+ }
818
+ return (empty_cell(), exists);
819
+ }