1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#![cfg_attr(rustfmt, rustfmt_skip)]

use crate::common::*;

// ---------------------------------------------------------------------------------------------- //
// bindings for `send*`
// SendBuilder<(Program, Payload, Value, Delay, GasLimit, ReservationId)>
// ---------------------------------------------------------------------------------------------- //

pub struct SendBuilder<Fields = ((), (), (), (), (), ())> {
    fields: Fields,
}

impl<Buffer: AsRef<[u8]>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, (), (), (), ())> {
    pub fn bytes(program: ActorId, payload: Buffer) -> Self {
        Self {
            fields: (ProgramW(program), PayloadBytesW(payload), (), (), (), ()),
        }
    }
}

impl<Encodable: Encode> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, (), (), (), ())> {
    pub fn encode(program: ActorId, payload: Encodable) -> Self {
        Self {
            fields: (ProgramW(program), PayloadEncodableW(payload), (), (), (), ()),
        }
    }
}

impl<Range: RangeBounds<usize>> SendBuilder<(ProgramW, PayloadInputW<Range>, (), (), (), ())> {
    pub fn input(program: ActorId, payload: Range) -> Self {
        Self {
            fields: (ProgramW(program), PayloadInputW(payload), (), (), (), ()),
        }
    }
}

impl<Program, Payload, Delay, GasLimit, ReservationId> SendBuilder<(Program, Payload, (), Delay, GasLimit, ReservationId)> {
    pub fn with_value(self, value: u128) -> SendBuilder<(Program, Payload, ValueW, Delay, GasLimit, ReservationId)> {
        let (program, payload, _, delay, gas_limit, reservation_id) = self.fields;
        SendBuilder {
            fields: (program, payload, ValueW(value), delay, gas_limit, reservation_id),
        }
    }
}

impl<Program, Payload, Value, GasLimit, ReservationId> SendBuilder<(Program, Payload, Value, (), GasLimit, ReservationId)> {
    pub fn with_delay(self, delay: u32) -> SendBuilder<(Program, Payload, Value, DelayW, GasLimit, ReservationId)> {
        let (program, payload, value, _, gas_limit, reservation_id) = self.fields;
        SendBuilder {
            fields: (program, payload, value, DelayW(delay), gas_limit, reservation_id),
        }
    }
}

impl<Program, Payload, Value, Delay, ReservationId: UnitTypeMarker> SendBuilder<(Program, Payload, Value, Delay, (), ReservationId)> {
    pub fn with_gas_limit(self, gas_limit: u64) -> SendBuilder<(Program, Payload, Value, Delay, GasLimitW, ReservationId)> {
        let (program, payload, value, delay, _, reservation_id) = self.fields;
        SendBuilder {
            fields: (program, payload, value, delay, GasLimitW(gas_limit), reservation_id),
        }
    }
}

impl<Program, Payload: PayloadWithGasReservationMarker, Value, Delay, GasLimit: UnitTypeMarker> SendBuilder<(Program, Payload, Value, Delay, GasLimit, ())> {
    pub fn with_gas_from_reservation(self, reservation_id: ReservationId) -> SendBuilder<(Program, Payload, Value, Delay, GasLimit, ReservationIdW)> {
        let (program, payload, value, delay, gas_limit, _) = self.fields;
        SendBuilder {
            fields: (program, payload, value, delay, gas_limit, ReservationIdW(reservation_id)),
        }
    }
}

impl<Program, Payload, Value, GasLimit, ReservationId> SendBuilder<(Program, Payload, Value, (), GasLimit, ReservationId)> {
    pub fn for_reply(self) -> SendBuilderForReply<(Program, Payload, Value, GasLimit, ReservationId, (), ())> {
        let (program, payload, value, _, gas_limit, reservation_id) = self.fields;
        SendBuilderForReply {
            fields: (program, payload, value, gas_limit, reservation_id, (), ()),
        }
    }

    #[allow(clippy::type_complexity)]
    pub fn for_reply_as<Decodable: Decode>(self) -> SendBuilderForReply<(Program, Payload, Value, GasLimit, ReservationId, (), DecodableW<Decodable>)> {
        let (program, payload, value, _, gas_limit, reservation_id) = self.fields;
        SendBuilderForReply {
            fields: (program, payload, value, gas_limit, reservation_id, (), DecodableW(PhantomData)),
        }
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, (), (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, _, _) = self.fields;
        send_bytes(program, payload, value.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, (), (), ReservationIdW)> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, _, ReservationIdW(reservation_id)) = self.fields;
        send_bytes_from_reservation(reservation_id, program, payload, value.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, (), GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, GasLimitW(gas_limit), _) = self.fields;
        send_bytes_with_gas(program, payload, gas_limit, value.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, DelayW, (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, DelayW(delay), _, _) = self.fields;
        send_bytes_delayed(program, payload, value.into().0, delay)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, DelayW, (), ReservationIdW)> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, DelayW(delay), _, ReservationIdW(reservation_id)) = self.fields;
        send_bytes_delayed_from_reservation(reservation_id, program, payload, value.into().0, delay)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadBytesW<Buffer>, Value, DelayW, GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadBytesW(payload), value, DelayW(delay), GasLimitW(gas_limit), _) = self.fields;
        send_bytes_with_gas_delayed(program, payload, gas_limit, value.into().0, delay)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, (), (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, _, _) = self.fields;
        send(program, payload, value.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, (), (), ReservationIdW)> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, _, ReservationIdW(reservation_id)) = self.fields;
        send_from_reservation(reservation_id, program, payload, value.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, (), GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, GasLimitW(gas_limit), _) = self.fields;
        send_with_gas(program, payload, gas_limit, value.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, DelayW, (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, DelayW(delay), _, _) = self.fields;
        send_delayed(program, payload, value.into().0, delay)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, DelayW, (), ReservationIdW)> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, DelayW(delay), _, ReservationIdW(reservation_id)) = self.fields;
        send_delayed_from_reservation(reservation_id, program, payload, value.into().0, delay)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadEncodableW<Encodable>, Value, DelayW, GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadEncodableW(payload), value, DelayW(delay), GasLimitW(gas_limit), _) = self.fields;
        send_with_gas_delayed(program, payload, gas_limit, value.into().0, delay)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadInputW<Range>, Value, (), (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadInputW(payload), value, _, _, _) = self.fields;
        send_input(program, value.into().0, payload)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadInputW<Range>, Value, (), GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadInputW(payload), value, _, GasLimitW(gas_limit), _) = self.fields;
        send_input_with_gas(program, gas_limit, value.into().0, payload)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadInputW<Range>, Value, DelayW, (), ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadInputW(payload), value, DelayW(delay), _, _) = self.fields;
        send_input_delayed(program, value.into().0, payload, delay)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>> SendBuilder<(ProgramW, PayloadInputW<Range>, Value, DelayW, GasLimitW, ())> {
    pub fn execute(self) -> Result<MessageId> {
        let (ProgramW(program), PayloadInputW(payload), value, DelayW(delay), GasLimitW(gas_limit), _) = self.fields;
        send_input_with_gas_delayed(program, gas_limit, value.into().0, payload, delay)
    }
}

// ---------------------------------------------------------------------------------------------- //
// bindings for `send*`: for_reply(), for_reply_as::<Decodable>()
// SendBuilderForReply<(Program, Payload, Value, GasLimit, ReservationId, ReplyDeposit, Decodable)>
// ---------------------------------------------------------------------------------------------- //

pub struct SendBuilderForReply<Fields = ((), (), (), (), (), ())> {
    fields: Fields,
}

impl<Program, Payload, Value, GasLimit, ReservationId, Decodable> SendBuilderForReply<(Program, Payload, Value, GasLimit, ReservationId, (), Decodable)> {
    pub fn with_reply_deposit(self, reply_deposit: u64) -> SendBuilderForReply<(Program, Payload, Value, GasLimit, ReservationId, ReplyDepositW, Decodable)> {
        let (program, payload, value, gas_limit, reservation_id, _, decodable) = self.fields;
        SendBuilderForReply {
            fields: (program, payload, value, gas_limit, reservation_id, ReplyDepositW(reply_deposit), decodable),
        }
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, (), (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_bytes_for_reply(program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, (), ReservationIdW, ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, ReservationIdW(reservation_id), reply_deposit, _) = self.fields;
        send_bytes_from_reservation_for_reply(reservation_id, program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, GasLimitW, (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadBytesW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_bytes_with_gas_for_reply(program, payload, gas_limit, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, (), (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_for_reply(program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, (), ReservationIdW, ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, ReservationIdW(reservation_id), reply_deposit, _) = self.fields;
        send_from_reservation_for_reply(reservation_id, program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, GasLimitW, (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadEncodableW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_with_gas_for_reply(program, payload, gas_limit, value.into().0, reply_deposit.into().0)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadInputW<Range>, Value, (), (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadInputW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_input_for_reply(program, value.into().0, payload, reply_deposit.into().0)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>> SendBuilderForReply<(ProgramW, PayloadInputW<Range>, Value, GasLimitW, (), ReplyDeposit, ())> {
    pub fn execute(self) -> Result<MessageFuture> {
        let (ProgramW(program), PayloadInputW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_input_with_gas_for_reply(program, gas_limit, value.into().0, payload, reply_deposit.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, (), (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_bytes_for_reply_as(program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, (), ReservationIdW, ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadBytesW(payload), value, _, ReservationIdW(reservation_id), reply_deposit, _) = self.fields;
        send_bytes_from_reservation_for_reply_as(reservation_id, program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Buffer: AsRef<[u8]>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadBytesW<Buffer>, Value, GasLimitW, (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadBytesW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_bytes_with_gas_for_reply_as(program, payload, gas_limit, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, (), (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_for_reply_as(program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, (), ReservationIdW, ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadEncodableW(payload), value, _, ReservationIdW(reservation_id), reply_deposit, _) = self.fields;
        send_from_reservation_for_reply_as(reservation_id, program, payload, value.into().0, reply_deposit.into().0)
    }
}

impl<Encodable: Encode, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadEncodableW<Encodable>, Value, GasLimitW, (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadEncodableW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_with_gas_for_reply_as(program, payload, gas_limit, value.into().0, reply_deposit.into().0)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadInputW<Range>, Value, (), (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadInputW(payload), value, _, _, reply_deposit, _) = self.fields;
        send_input_for_reply_as(program, value.into().0, payload, reply_deposit.into().0)
    }
}

impl<Range: RangeBounds<usize>, Value: Into<ValueW>, ReplyDeposit: Into<ReplyDepositW>, Decodable: Decode> SendBuilderForReply<(ProgramW, PayloadInputW<Range>, Value, GasLimitW, (), ReplyDeposit, DecodableW<Decodable>)> {
    pub fn execute(self) -> Result<CodecMessageFuture<Decodable>> {
        let (ProgramW(program), PayloadInputW(payload), value, GasLimitW(gas_limit), _, reply_deposit, _) = self.fields;
        send_input_with_gas_for_reply_as(program, gas_limit, value.into().0, payload, reply_deposit.into().0)
    }
}