1use abi_stable::std_types::{ROption, RString, RVec};
2use abi_stable::StableAbi;
3use picodata_plugin_proc_macro::internal;
4use tarantool::session::UserId;
5use tarantool::space::{SpaceId, UpdateOps};
6use tarantool::tuple::{ToTupleBuffer, Tuple};
7
8#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
10#[repr(u8)]
11pub enum DmlInner {
12 Insert {
13 table: SpaceId,
14 tuple: RVec<u8>,
15 initiator: UserId,
16 },
17 Replace {
18 table: SpaceId,
19 tuple: RVec<u8>,
20 initiator: UserId,
21 },
22 Update {
23 table: SpaceId,
24 key: RVec<u8>,
25 ops: RVec<RVec<u8>>,
26 initiator: UserId,
27 },
28 Delete {
29 table: SpaceId,
30 key: RVec<u8>,
31 initiator: UserId,
32 },
33}
34
35#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
37#[repr(C)]
38pub struct Dml(
39 pub DmlInner,
44);
45
46impl Dml {
47 pub fn insert(space_id: SpaceId, tuple: Tuple, initiator: UserId) -> Self {
49 Dml(DmlInner::Insert {
50 table: space_id,
51 tuple: RVec::from(tuple.to_vec()),
52 initiator,
53 })
54 }
55
56 pub fn replace(space_id: SpaceId, tuple: Tuple, initiator: UserId) -> Self {
58 Dml(DmlInner::Replace {
59 table: space_id,
60 tuple: RVec::from(tuple.to_vec()),
61 initiator,
62 })
63 }
64
65 pub fn update(
67 space_id: SpaceId,
68 key: &impl ToTupleBuffer,
69 ops: UpdateOps,
70 initiator: UserId,
71 ) -> tarantool::Result<Self> {
72 let tb = key.to_tuple_buffer()?;
73 let raw_key = Vec::from(tb);
74
75 let ops: RVec<_> = ops
76 .into_inner()
77 .into_iter()
78 .map(|tb| RVec::from(Vec::from(tb)))
79 .collect();
80
81 Ok(Dml(DmlInner::Update {
82 table: space_id,
83 key: RVec::from(raw_key),
84 ops,
85 initiator,
86 }))
87 }
88
89 pub fn delete(
91 space_id: SpaceId,
92 key: &impl ToTupleBuffer,
93 initiator: UserId,
94 ) -> tarantool::Result<Self> {
95 let tb = key.to_tuple_buffer()?;
96 let raw_key = Vec::from(tb);
97
98 Ok(Dml(DmlInner::Delete {
99 table: space_id,
100 key: RVec::from(raw_key),
101 initiator,
102 }))
103 }
104}
105
106#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
108#[repr(u8)]
109pub enum OpInner {
110 Nop,
111 Dml(Dml),
112 BatchDml(RVec<Dml>),
113}
114
115#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
117#[repr(C)]
118pub struct Op(
119 pub OpInner,
124);
125
126impl Op {
127 pub fn nop() -> Self {
129 Self(OpInner::Nop)
130 }
131
132 pub fn dml(dml: Dml) -> Self {
134 Self(OpInner::Dml(dml))
135 }
136
137 pub fn dml_batch(batch: Vec<Dml>) -> Self {
139 Self(OpInner::BatchDml(RVec::from(batch)))
140 }
141}
142
143#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
144#[repr(C)]
145pub struct Bound {
146 pub is_included: bool,
147 pub key: RVec<u8>,
148}
149
150impl Bound {
151 pub fn new(is_included: bool, key: &impl ToTupleBuffer) -> tarantool::Result<Self> {
152 let tb = key.to_tuple_buffer()?;
153 let raw_key = Vec::from(tb);
154
155 Ok(Self {
156 is_included,
157 key: RVec::from(raw_key),
158 })
159 }
160}
161
162#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
163#[repr(C)]
164pub struct Range {
165 pub table: SpaceId,
166 pub key_min: Bound,
167 pub key_max: Bound,
168}
169
170#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
171#[repr(C)]
172pub struct Predicate {
173 pub index: u64,
174 pub term: u64,
175 pub ranges: RVec<Range>,
176}
177
178impl Predicate {
179 pub fn new(index: u64, term: u64, ranges: Vec<Range>) -> Self {
180 Self {
181 index,
182 term,
183 ranges: RVec::from(ranges),
184 }
185 }
186}
187
188::tarantool::define_str_enum! {
189 #[derive(Default, StableAbi)]
191 #[repr(C)]
192 pub enum StateVariant {
193 #[default]
195 Offline = "Offline",
196 Online = "Online",
198 Expelled = "Expelled",
200 }
201}
202
203#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
204#[repr(C)]
205pub struct State {
206 variant: StateVariant,
207 incarnation: u64,
208}
209
210impl State {
211 pub fn new(variant: StateVariant, incarnation: u64) -> Self {
212 Self {
213 variant,
214 incarnation,
215 }
216 }
217
218 pub fn name(&self) -> StateVariant {
223 self.variant
224 }
225
226 pub fn incarnation(&self) -> u64 {
228 self.incarnation
229 }
230}
231
232#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
233#[repr(C)]
234pub struct InstanceInfo {
235 raft_id: u64,
236 advertise_address: RString,
237 name: RString,
238 uuid: RString,
239 replicaset_name: RString,
240 replicaset_uuid: RString,
241 cluster_name: RString,
242 current_state: State,
243 target_state: State,
244 tier: RString,
245}
246
247impl InstanceInfo {
248 #[allow(clippy::too_many_arguments)]
249 pub fn new(
250 raft_id: u64,
251 advertise_address: String,
252 name: String,
253 instance_uuid: String,
254 replicaset_name: String,
255 replicaset_uuid: String,
256 cluster_name: String,
257 current_state: State,
258 target_state: State,
259 tier: String,
260 ) -> Self {
261 Self {
262 raft_id,
263 advertise_address: RString::from(advertise_address),
264 name: RString::from(name),
265 uuid: RString::from(instance_uuid),
266 replicaset_name: RString::from(replicaset_name),
267 replicaset_uuid: RString::from(replicaset_uuid),
268 cluster_name: RString::from(cluster_name),
269 current_state,
270 target_state,
271 tier: RString::from(tier),
272 }
273 }
274
275 pub fn raft_id(&self) -> u64 {
277 self.raft_id
278 }
279
280 pub fn advertise_address(&self) -> &str {
282 self.advertise_address.as_str()
283 }
284
285 pub fn name(&self) -> &str {
287 self.name.as_str()
288 }
289
290 pub fn uuid(&self) -> &str {
292 self.uuid.as_str()
293 }
294
295 pub fn replicaset_name(&self) -> &str {
297 self.replicaset_name.as_str()
298 }
299
300 pub fn replicaset_uuid(&self) -> &str {
302 self.replicaset_uuid.as_str()
303 }
304
305 pub fn cluster_name(&self) -> &str {
307 self.cluster_name.as_str()
308 }
309
310 pub fn current_state(&self) -> &State {
312 &self.current_state
313 }
314
315 pub fn target_state(&self) -> &State {
317 &self.target_state
318 }
319
320 pub fn tier(&self) -> &str {
322 self.tier.as_str()
323 }
324}
325
326#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
327#[repr(C)]
328pub struct RaftInfo {
329 id: u64,
330 term: u64,
331 applied: u64,
332 leader_id: u64,
333 state: RaftState,
334}
335
336#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
337#[repr(u8)]
338pub enum RaftState {
339 Follower,
340 Candidate,
341 Leader,
342 PreCandidate,
343}
344
345impl RaftInfo {
346 pub fn new(id: u64, term: u64, applied: u64, leader_id: u64, state: RaftState) -> Self {
347 Self {
348 id,
349 term,
350 applied,
351 leader_id,
352 state,
353 }
354 }
355
356 pub fn id(&self) -> u64 {
358 self.id
359 }
360
361 pub fn term(&self) -> u64 {
363 self.term
364 }
365
366 pub fn applied(&self) -> u64 {
368 self.applied
369 }
370
371 pub fn leader_id(&self) -> u64 {
373 self.leader_id
374 }
375
376 pub fn state(&self) -> RaftState {
382 self.state
383 }
384}
385
386#[internal]
394#[derive(StableAbi, Clone, Debug)]
395#[repr(C)]
396pub struct FfiListenerConfig {
397 pub listen: RString,
399 pub advertise: RString,
401 pub tls: ROption<FfiListenerTlsConfig>,
403}
404
405#[internal]
409#[derive(StableAbi, Clone, Debug)]
410#[repr(C)]
411pub struct FfiListenerTlsConfig {
412 pub cert_chain_pem: RVec<u8>,
414 pub key_pem: RVec<u8>,
416 pub mtls_ca_chain_pem: ROption<RVec<u8>>,
418}
419
420#[internal]
421#[derive(StableAbi, Clone, Debug)]
422#[repr(u8)]
423pub enum FfiListenerConfigError {
424 Undefined,
426 Disabled,
428 Malformed,
429}