1use std::cmp::Ordering;
12use std::io::Cursor;
13use std::os::raw::{c_char, c_int};
14use std::ptr::copy_nonoverlapping;
15use std::slice::from_raw_parts;
16
17use num_traits::ToPrimitive;
18use rmp::Marker;
19use serde::{de::DeserializeOwned, Serialize};
20
21use crate::error::{Error, TarantoolError};
22
23pub struct Tuple {
25 ptr: *mut ffi::BoxTuple,
26}
27
28impl Tuple {
29 pub fn from_struct<T>(value: &T) -> Result<Self, Error>
35 where
36 T: AsTuple,
37 {
38 let format = TupleFormat::default();
39 let buf = value.serialize_as_tuple()?;
40 let buf_ptr = buf.as_ptr() as *const c_char;
41 let tuple_ptr = unsafe {
42 ffi::box_tuple_new(format.inner, buf_ptr, buf_ptr.offset(buf.len() as isize))
43 };
44
45 unsafe { ffi::box_tuple_ref(tuple_ptr) };
46 Ok(Tuple { ptr: tuple_ptr })
47 }
48
49 pub(crate) fn from_raw_data(data_ptr: *mut c_char, len: u32) -> Self {
50 let format = TupleFormat::default();
51 let tuple_ptr =
52 unsafe { ffi::box_tuple_new(format.inner, data_ptr, data_ptr.offset(len as isize)) };
53
54 unsafe { ffi::box_tuple_ref(tuple_ptr) };
55 Tuple { ptr: tuple_ptr }
56 }
57
58 pub(crate) fn from_ptr(ptr: *mut ffi::BoxTuple) -> Self {
59 unsafe { ffi::box_tuple_ref(ptr) };
60 Tuple { ptr }
61 }
62
63 pub fn len(&self) -> u32 {
65 unsafe { ffi::box_tuple_field_count(self.ptr) }
66 }
67
68 pub fn bsize(&self) -> usize {
78 unsafe { ffi::box_tuple_bsize(self.ptr) }
79 }
80
81 pub fn format(&self) -> TupleFormat {
83 TupleFormat {
84 inner: unsafe { ffi::box_tuple_format(self.ptr) },
85 }
86 }
87
88 pub fn iter(&self) -> Result<TupleIterator, Error> {
108 let inner = unsafe { ffi::box_tuple_iterator(self.ptr) };
109 if inner.is_null() {
110 Err(TarantoolError::last().into())
111 } else {
112 Ok(TupleIterator { inner })
113 }
114 }
115
116 pub fn field<T>(&self, fieldno: u32) -> Result<Option<T>, Error>
126 where
127 T: DeserializeOwned,
128 {
129 let result_ptr = unsafe { ffi::box_tuple_field(self.ptr, fieldno) };
130 field_value_from_ptr(result_ptr as *mut u8)
131 }
132
133 pub fn into_struct<T>(self) -> Result<T, Error>
135 where
136 T: DeserializeOwned,
137 {
138 let raw_data_size = self.bsize();
139 let mut raw_data = Vec::<u8>::with_capacity(raw_data_size);
140
141 let actual_size = unsafe {
142 ffi::box_tuple_to_buf(self.ptr, raw_data.as_ptr() as *mut c_char, raw_data_size)
143 };
144 if actual_size < 0 {
145 return Err(TarantoolError::last().into());
146 }
147
148 unsafe { raw_data.set_len(actual_size as usize) };
149 Ok(rmp_serde::from_read::<_, T>(Cursor::new(raw_data))?)
150 }
151
152 pub(crate) fn into_ptr(self) -> *mut ffi::BoxTuple {
153 self.ptr
154 }
155}
156
157impl Drop for Tuple {
158 fn drop(&mut self) {
159 unsafe { ffi::box_tuple_unref(self.ptr) };
160 }
161}
162
163impl Clone for Tuple {
164 fn clone(&self) -> Self {
165 unsafe { ffi::box_tuple_ref(self.ptr) };
166 Tuple { ptr: self.ptr }
167 }
168}
169
170pub trait AsTuple: Serialize {
172 fn serialize_as_tuple(&self) -> Result<TupleBuffer, Error> {
176 Ok(rmp_serde::to_vec(self)?.into())
177 }
178}
179
180impl AsTuple for () {
181 fn serialize_as_tuple(&self) -> Result<TupleBuffer, Error> {
182 Ok(rmp_serde::to_vec(&Vec::<()>::new())?.into())
183 }
184}
185
186impl<T> AsTuple for (T,) where T: Serialize {}
187impl<T> AsTuple for Vec<T> where T: Serialize {}
188
189impl<Ta, Tb> AsTuple for (Ta, Tb)
190where
191 Ta: Serialize,
192 Tb: Serialize,
193{
194}
195
196impl<Ta, Tb, Tc> AsTuple for (Ta, Tb, Tc)
197where
198 Ta: Serialize,
199 Tb: Serialize,
200 Tc: Serialize,
201{
202}
203
204impl<Ta, Tb, Tc, Td> AsTuple for (Ta, Tb, Tc, Td)
205where
206 Ta: Serialize,
207 Tb: Serialize,
208 Tc: Serialize,
209 Td: Serialize,
210{
211}
212
213pub enum TupleBuffer {
218 Vector(Vec<u8>),
219 TransactionScoped { ptr: *mut u8, size: usize },
220}
221
222impl TupleBuffer {
223 pub fn as_ptr(&self) -> *const u8 {
225 match self {
226 TupleBuffer::Vector(vec) => vec.as_ptr(),
227 TupleBuffer::TransactionScoped { ptr, size: _ } => ptr.clone(),
228 }
229 }
230
231 pub fn len(&self) -> usize {
233 match self {
234 TupleBuffer::Vector(vec) => vec.len(),
235 TupleBuffer::TransactionScoped { ptr: _, size } => size.clone(),
236 }
237 }
238}
239
240impl From<Vec<u8>> for TupleBuffer {
241 fn from(buf: Vec<u8>) -> Self {
242 if unsafe { crate::transaction::ffi::box_txn() } {
243 let size = buf.len();
244 unsafe {
245 let ptr = crate::transaction::ffi::box_txn_alloc(size) as *mut u8;
246 copy_nonoverlapping(buf.as_ptr(), ptr, size);
247
248 Self::TransactionScoped { ptr, size }
249 }
250 } else {
251 Self::Vector(buf)
252 }
253 }
254}
255
256pub struct TupleFormat {
261 inner: *mut ffi::BoxTupleFormat,
262}
263
264impl Default for TupleFormat {
265 fn default() -> Self {
266 TupleFormat {
267 inner: unsafe { ffi::box_tuple_format_default() },
268 }
269 }
270}
271
272pub struct TupleIterator {
274 inner: *mut ffi::BoxTupleIterator,
275}
276
277impl TupleIterator {
278 pub fn position(&self) -> u32 {
285 unsafe { ffi::box_tuple_position(self.inner) }
286 }
287
288 pub fn rewind(&mut self) {
290 unsafe { ffi::box_tuple_rewind(self.inner) }
291 }
292
293 pub fn seek<T>(&mut self, fieldno: u32) -> Result<Option<T>, Error>
303 where
304 T: DeserializeOwned,
305 {
306 let result_ptr = unsafe { ffi::box_tuple_seek(self.inner, fieldno) };
307 field_value_from_ptr(result_ptr as *mut u8)
308 }
309
310 pub fn next<T>(&mut self) -> Result<Option<T>, Error>
320 where
321 T: DeserializeOwned,
322 {
323 let result_ptr = unsafe { ffi::box_tuple_next(self.inner) };
324 field_value_from_ptr(result_ptr as *mut u8)
325 }
326
327 pub fn update(&mut self) {}
328}
329
330impl Drop for TupleIterator {
331 fn drop(&mut self) {
332 unsafe { ffi::box_tuple_iterator_free(self.inner) }
333 }
334}
335
336impl TupleIterator {}
337
338#[repr(u32)]
339#[derive(Debug, ToPrimitive)]
340pub enum FieldType {
341 Any = 0,
342 Unsigned,
343 String,
344 Number,
345 Double,
346 Integer,
347 Boolean,
348 Varbinary,
349 Scalar,
350 Decimal,
351 Uuid,
352 Array,
353 Map,
354}
355
356pub struct KeyDef {
357 inner: *mut ffi::BoxKeyDef,
358}
359
360pub struct KeyDefItem {
361 pub field_id: u32,
362 pub field_type: FieldType,
363}
364
365impl KeyDef {
366 pub fn new(items: Vec<KeyDefItem>) -> Self {
371 let size = items.len();
372 let mut ids = Vec::with_capacity(size);
373 let mut types = Vec::with_capacity(size);
374 for item in items {
375 ids.push(item.field_id);
376 types.push(item.field_type.to_u32().unwrap());
377 }
378
379 KeyDef {
380 inner: unsafe {
381 ffi::box_key_def_new(ids.as_mut_ptr(), types.as_mut_ptr(), size as u32)
382 },
383 }
384 }
385
386 pub fn compare(&self, tuple_a: &Tuple, tuple_b: &Tuple) -> Ordering {
396 unsafe { ffi::box_tuple_compare(tuple_a.ptr, tuple_b.ptr, self.inner) }.cmp(&0)
397 }
398
399 pub fn compare_with_key<K>(&self, tuple: &Tuple, key: &K) -> Ordering
409 where
410 K: AsTuple,
411 {
412 let key_buf = key.serialize_as_tuple().unwrap();
413 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
414 unsafe { ffi::box_tuple_compare_with_key(tuple.ptr, key_buf_ptr, self.inner) }.cmp(&0)
415 }
416}
417
418impl Drop for KeyDef {
419 fn drop(&mut self) {
420 unsafe { ffi::box_key_def_delete(self.inner) }
421 }
422}
423
424fn field_value_from_ptr<T>(value_ptr: *mut u8) -> Result<Option<T>, Error>
425where
426 T: DeserializeOwned,
427{
428 if value_ptr.is_null() {
429 return Ok(None);
430 }
431
432 let marker = Marker::from_u8(unsafe { *value_ptr });
433 Ok(match marker {
434 Marker::FixStr(str_len) => {
435 let buf = unsafe { from_raw_parts(value_ptr as *mut u8, (str_len + 1) as usize) };
436 Some(rmp_serde::from_read_ref::<_, T>(buf)?)
437 }
438
439 Marker::Str8 | Marker::Str16 | Marker::Str32 => {
440 let head = unsafe { from_raw_parts(value_ptr as *mut u8, 9) };
441 let len = rmp::decode::read_str_len(&mut Cursor::new(head))?;
442
443 let buf = unsafe { from_raw_parts(value_ptr as *mut u8, (len + 9) as usize) };
444 Some(rmp_serde::from_read_ref::<_, T>(buf)?)
445 }
446
447 Marker::FixPos(_)
448 | Marker::FixNeg(_)
449 | Marker::Null
450 | Marker::True
451 | Marker::False
452 | Marker::U8
453 | Marker::U16
454 | Marker::U32
455 | Marker::U64
456 | Marker::I8
457 | Marker::I16
458 | Marker::I32
459 | Marker::I64
460 | Marker::F32
461 | Marker::F64 => {
462 let buf = unsafe { from_raw_parts(value_ptr as *mut u8, 9) };
463 Some(rmp_serde::from_read_ref::<_, T>(buf)?)
464 }
465
466 _ => None,
467 })
468}
469
470#[repr(C)]
471pub struct FunctionCtx {
472 inner: *mut ffi::BoxFunctionCtx,
473}
474
475impl FunctionCtx {
476 pub fn return_tuple(self, tuple: Tuple) -> Result<c_int, Error> {
482 let result = unsafe { ffi::box_return_tuple(self.inner, tuple.ptr) };
483 if result < 0 {
484 Err(TarantoolError::last().into())
485 } else {
486 Ok(result)
487 }
488 }
489
490 pub fn return_mp<T>(self, value: &T) -> Result<c_int, Error>
501 where
502 T: AsTuple,
503 {
504 let buf = value.serialize_as_tuple().unwrap();
505 let buf_ptr = buf.as_ptr() as *const c_char;
506 let result =
507 unsafe { ffi::box_return_mp(self.inner, buf_ptr, buf_ptr.offset(buf.len() as isize)) };
508
509 if result < 0 {
510 Err(TarantoolError::last().into())
511 } else {
512 Ok(result)
513 }
514 }
515}
516
517#[repr(C)]
518pub struct FunctionArgs {
519 pub args: *const c_char,
520 pub args_end: *const c_char,
521}
522
523impl Into<Tuple> for FunctionArgs {
524 fn into(self) -> Tuple {
525 let len = (self.args_end as usize) - (self.args as usize);
526 Tuple::from_raw_data(self.args as *mut c_char, len as u32)
527 }
528}
529
530pub fn session_push<T>(value: &T) -> Result<(), Error>
535where
536 T: AsTuple,
537{
538 let buf = value.serialize_as_tuple().unwrap();
539 let buf_ptr = buf.as_ptr() as *const c_char;
540 if unsafe { ffi::box_session_push(buf_ptr, buf_ptr.offset(buf.len() as isize)) } < 0 {
541 Err(TarantoolError::last().into())
542 } else {
543 Ok(())
544 }
545}
546
547pub(crate) mod ffi {
548 use std::os::raw::{c_char, c_int};
549
550 #[repr(C)]
551 pub struct BoxTuple {
552 _unused: [u8; 0],
553 }
554
555 extern "C" {
556 pub fn box_tuple_new(
557 format: *mut BoxTupleFormat,
558 data: *const c_char,
559 end: *const c_char,
560 ) -> *mut BoxTuple;
561 pub fn box_tuple_ref(tuple: *mut BoxTuple) -> c_int;
562 pub fn box_tuple_unref(tuple: *mut BoxTuple);
563 pub fn box_tuple_field_count(tuple: *const BoxTuple) -> u32;
564 pub fn box_tuple_bsize(tuple: *const BoxTuple) -> usize;
565 pub fn box_tuple_to_buf(tuple: *const BoxTuple, buf: *mut c_char, size: usize) -> isize;
566 }
567
568 #[repr(C)]
569 pub struct BoxTupleFormat {
570 _unused: [u8; 0],
571 }
572
573 extern "C" {
574 pub fn box_tuple_format_default() -> *mut BoxTupleFormat;
575 pub fn box_tuple_format(tuple: *const BoxTuple) -> *mut BoxTupleFormat;
576 pub fn box_tuple_field(tuple: *const BoxTuple, fieldno: u32) -> *const c_char;
577 }
578
579 #[repr(C)]
580 pub struct BoxTupleIterator {
581 _unused: [u8; 0],
582 }
583
584 extern "C" {
585 pub fn box_tuple_iterator(tuple: *mut BoxTuple) -> *mut BoxTupleIterator;
586 pub fn box_tuple_iterator_free(it: *mut BoxTupleIterator);
587 pub fn box_tuple_position(it: *mut BoxTupleIterator) -> u32;
588 pub fn box_tuple_rewind(it: *mut BoxTupleIterator);
589 pub fn box_tuple_seek(it: *mut BoxTupleIterator, fieldno: u32) -> *const c_char;
590 pub fn box_tuple_next(it: *mut BoxTupleIterator) -> *const c_char;
591 }
592
593 #[repr(C)]
594 pub struct BoxKeyDef {
595 _unused: [u8; 0],
596 }
597
598 extern "C" {
599 pub fn box_key_def_new(
600 fields: *mut u32,
601 types: *mut u32,
602 part_count: u32,
603 ) -> *mut BoxKeyDef;
604 pub fn box_key_def_delete(key_def: *mut BoxKeyDef);
605 pub fn box_tuple_compare(
606 tuple_a: *mut BoxTuple,
607 tuple_b: *mut BoxTuple,
608 key_def: *mut BoxKeyDef,
609 ) -> c_int;
610 pub fn box_tuple_compare_with_key(
611 tuple_a: *mut BoxTuple,
612 key_b: *const c_char,
613 key_def: *mut BoxKeyDef,
614 ) -> c_int;
615 }
616
617 #[repr(C)]
618 pub struct BoxFunctionCtx {
619 _unused: [u8; 0],
620 }
621
622 extern "C" {
623 pub fn box_return_tuple(ctx: *mut BoxFunctionCtx, tuple: *mut BoxTuple) -> c_int;
624 pub fn box_return_mp(
625 ctx: *mut BoxFunctionCtx,
626 mp: *const c_char,
627 mp_end: *const c_char,
628 ) -> c_int;
629 pub fn box_session_push(data: *const c_char, data_end: *const c_char) -> c_int;
630 }
631}