1use std::borrow::Cow;
12use std::cmp::Ordering;
13use std::convert::TryFrom;
14use std::ffi::{CStr, CString};
15use std::fmt::{self, Debug, Formatter};
16use std::io::Write;
17use std::ops::Range;
18use std::os::raw::{c_char, c_int};
19use std::ptr::{null, NonNull};
20
21use rmp::Marker;
22use serde::Serialize;
23
24use crate::error::{self, Error, Result, TarantoolError};
25#[cfg(feature = "picodata")]
26use crate::ffi::sql::PortC;
27use crate::ffi::tarantool as ffi;
28use crate::index;
29use crate::tlua;
30
31pub struct Tuple {
33 ptr: NonNull<ffi::BoxTuple>,
34}
35
36impl Debug for Tuple {
37 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
38 if let Ok(v) = self.decode::<rmpv::Value>() {
39 f.debug_tuple("Tuple").field(&v).finish()
40 } else {
41 f.debug_tuple("Tuple").field(&self.to_vec()).finish()
43 }
44 }
45}
46
47impl Tuple {
48 #[inline]
50 pub fn new<T>(value: &T) -> Result<Self>
51 where
52 T: ToTupleBuffer + ?Sized,
53 {
54 Ok(Self::from(&value.to_tuple_buffer()?))
55 }
56
57 #[inline(always)]
61 pub unsafe fn from_raw_data(data: *mut c_char, len: u32) -> Self {
62 let format = TupleFormat::default();
63 let tuple_ptr = ffi::box_tuple_new(format.inner, data as _, data.add(len as _) as _);
64
65 Self::from_ptr(NonNull::new_unchecked(tuple_ptr))
66 }
67
68 #[inline(always)]
71 pub unsafe fn from_slice(data: &[u8]) -> Self {
72 let format = TupleFormat::default();
73 let Range { start, end } = data.as_ptr_range();
74 let tuple_ptr = ffi::box_tuple_new(format.inner, start as _, end as _);
75
76 Self::from_ptr(NonNull::new_unchecked(tuple_ptr))
77 }
78
79 #[inline]
80 pub fn try_from_slice(data: &[u8]) -> Result<Self> {
81 let data = validate_msgpack(data)?;
82 unsafe { Ok(Self::from_slice(data)) }
83 }
84
85 #[inline(always)]
86 pub fn from_ptr(mut ptr: NonNull<ffi::BoxTuple>) -> Self {
87 unsafe { ffi::box_tuple_ref(ptr.as_mut()) };
88 Tuple { ptr }
89 }
90
91 #[inline(always)]
92 pub fn try_from_ptr(ptr: *mut ffi::BoxTuple) -> Option<Self> {
93 NonNull::new(ptr).map(Self::from_ptr)
94 }
95
96 #[inline(always)]
98 pub fn len(&self) -> u32 {
99 unsafe { ffi::box_tuple_field_count(self.ptr.as_ptr()) }
100 }
101
102 #[inline(always)]
103 pub fn is_empty(&self) -> bool {
104 self.len() == 0
105 }
106
107 #[inline(always)]
117 pub fn bsize(&self) -> usize {
118 unsafe { self.ptr.as_ref().bsize() }
119 }
120
121 #[inline(always)]
123 pub fn format(&self) -> TupleFormat {
124 let inner = unsafe { ffi::box_tuple_format(self.ptr.as_ptr()) };
126
127 unsafe {
129 if inner != ffi::box_tuple_format_default() {
130 ffi::box_tuple_format_ref(inner)
131 }
132 }
133
134 TupleFormat { inner }
135 }
136
137 #[inline]
159 pub fn iter(&self) -> Result<TupleIterator> {
160 let inner = unsafe { ffi::box_tuple_iterator(self.ptr.as_ptr()) };
161 if inner.is_null() {
162 Err(TarantoolError::last().into())
163 } else {
164 Ok(TupleIterator { inner })
165 }
166 }
167
168 #[inline(always)]
179 pub fn field<'a, T>(&'a self, fieldno: u32) -> Result<Option<T>>
180 where
181 T: Decode<'a>,
182 {
183 unsafe {
184 let field_ptr = ffi::box_tuple_field(self.ptr.as_ptr(), fieldno);
185 field_value_from_ptr(field_ptr as _)
186 }
187 }
188
189 #[inline(always)]
212 pub fn try_get<'a, I, T>(&'a self, key: I) -> Result<Option<T>>
213 where
214 I: TupleIndex,
215 T: Decode<'a>,
216 {
217 key.get_field(self)
218 }
219
220 #[inline(always)]
243 #[track_caller]
244 pub fn get<'a, I, T>(&'a self, key: I) -> Option<T>
245 where
246 I: TupleIndex,
247 T: Decode<'a>,
248 {
249 self.try_get(key).expect("Error during getting tuple field")
250 }
251
252 #[inline]
269 pub fn decode<T>(&self) -> Result<T>
270 where
271 T: DecodeOwned,
272 {
273 #[cfg(feature = "picodata")]
274 return Decode::decode(self.data());
275 #[cfg(not(feature = "picodata"))]
276 return Decode::decode(&self.to_vec());
277 }
278
279 #[inline]
283 pub fn to_vec(&self) -> Vec<u8> {
284 let size = self.bsize();
285 let mut buf = Vec::with_capacity(size);
286
287 unsafe {
288 let actual_size = ffi::box_tuple_to_buf(self.ptr.as_ptr(), buf.as_ptr() as _, size);
289 buf.set_len(actual_size as usize);
290 }
291
292 buf
293 }
294
295 #[inline(always)]
297 pub fn as_ptr(&self) -> *mut ffi::BoxTuple {
298 self.ptr.as_ptr()
299 }
300}
301
302pub trait TupleIndex {
311 fn get_field<'a, T>(self, tuple: &'a Tuple) -> Result<Option<T>>
312 where
313 T: Decode<'a>;
314}
315
316impl TupleIndex for u32 {
317 #[inline(always)]
318 fn get_field<'a, T>(self, tuple: &'a Tuple) -> Result<Option<T>>
319 where
320 T: Decode<'a>,
321 {
322 tuple.field(self)
323 }
324}
325
326impl TupleIndex for &str {
327 #[inline(always)]
328 fn get_field<'a, T>(self, tuple: &'a Tuple) -> Result<Option<T>>
329 where
330 T: Decode<'a>,
331 {
332 use once_cell::sync::Lazy;
333 use std::io::{Error as IOError, ErrorKind};
334 static API: Lazy<std::result::Result<Api, libloading::Error>> = Lazy::new(|| unsafe {
335 let lib = libloading::os::unix::Library::this();
336 let err = match lib.get(ffi::TUPLE_FIELD_BY_PATH_NEW_API.as_bytes()) {
337 Ok(api) => return Ok(Api::New(*api)),
338 Err(e) => e,
339 };
340 if let Ok(api) = lib.get(ffi::TUPLE_FIELD_BY_PATH_OLD_API.as_bytes()) {
341 return Ok(Api::Old(*api));
342 }
343 Err(err)
344 });
345
346 return match API.as_ref() {
347 Ok(Api::New(api)) => unsafe {
348 let field_ptr = api(tuple.ptr.as_ptr(), self.as_ptr() as _, self.len() as _, 1);
349 field_value_from_ptr(field_ptr as _)
350 },
351 Ok(Api::Old(api)) => unsafe {
352 let data_offset = tuple.ptr.as_ref().data_offset() as _;
353 let data = tuple.ptr.as_ptr().cast::<c_char>().add(data_offset);
354 let field_ptr = api(
355 tuple.format().inner,
356 data,
357 data as _,
358 self.as_ptr() as _,
359 self.len() as _,
360 tlua::util::hash(self),
361 );
362 field_value_from_ptr(field_ptr as _)
363 },
364 Err(e) => Err(Error::IO(IOError::new(ErrorKind::Unsupported, e))),
365 };
366
367 enum Api {
368 Old(
370 extern "C" fn(
371 format: *const ffi::BoxTupleFormat,
372 tuple: *const c_char,
373 field_map: *const u32,
374 path: *const c_char,
375 path_len: u32,
376 path_hash: u32,
377 ) -> *const c_char,
378 ),
379 New(
381 extern "C" fn(
382 tuple: *const ffi::BoxTuple,
383 path: *const c_char,
384 path_len: u32,
385 index_base: i32,
386 ) -> *const c_char,
387 ),
388 }
389 }
390}
391
392impl From<&TupleBuffer> for Tuple {
393 #[inline(always)]
394 fn from(buf: &TupleBuffer) -> Self {
395 unsafe { Self::from_raw_data(buf.as_ptr() as _, buf.len() as _) }
396 }
397}
398
399impl Drop for Tuple {
400 #[inline(always)]
401 fn drop(&mut self) {
402 unsafe { ffi::box_tuple_unref(self.ptr.as_ptr()) };
403 }
404}
405
406impl Clone for Tuple {
407 #[inline(always)]
408 fn clone(&self) -> Self {
409 unsafe { ffi::box_tuple_ref(self.ptr.as_ptr()) };
410 Tuple { ptr: self.ptr }
411 }
412}
413
414impl<'de> serde_bytes::Deserialize<'de> for Tuple {
415 #[inline]
416 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
417 where
418 D: serde::Deserializer<'de>,
419 {
420 let data: &[u8] = serde_bytes::Deserialize::deserialize(deserializer)?;
421 Self::try_from_slice(data).map_err(serde::de::Error::custom)
422 }
423}
424
425pub trait ToTupleBuffer {
432 #[inline]
433 fn to_tuple_buffer(&self) -> Result<TupleBuffer> {
434 let mut buf = Vec::with_capacity(128);
435 self.write_tuple_data(&mut buf)?;
436 TupleBuffer::try_from_vec(buf)
437 }
438
439 #[inline(always)]
448 fn tuple_data(&self) -> Option<&[u8]> {
449 None
450 }
451
452 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()>;
453}
454
455impl ToTupleBuffer for Tuple {
456 #[inline(always)]
457 fn to_tuple_buffer(&self) -> Result<TupleBuffer> {
458 Ok(TupleBuffer::from(self))
459 }
460
461 #[cfg(feature = "picodata")]
462 #[inline(always)]
463 fn tuple_data(&self) -> Option<&[u8]> {
464 Some(self.data())
465 }
466
467 #[inline]
468 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()> {
469 #[cfg(feature = "picodata")]
470 w.write_all(self.data())?;
471 #[cfg(not(feature = "picodata"))]
472 w.write_all(&self.to_vec())?;
473 Ok(())
474 }
475}
476
477impl<T> ToTupleBuffer for T
478where
479 T: ?Sized,
480 T: Encode,
481{
482 #[inline(always)]
483 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()> {
484 self.encode(w)
485 }
486}
487
488pub trait Encode: Serialize {
497 #[inline(always)]
498 fn encode(&self, w: &mut impl Write) -> Result<()> {
499 rmp_serde::encode::write(w, self).map_err(Into::into)
500 }
501}
502
503impl<T> Encode for &'_ T
504where
505 T: Encode,
506{
507 #[inline(always)]
508 fn encode(&self, w: &mut impl Write) -> Result<()> {
509 T::encode(*self, w)
510 }
511}
512
513impl Encode for () {
514 #[inline(always)]
515 fn encode(&self, w: &mut impl Write) -> Result<()> {
516 rmp_serde::encode::write(w, &Vec::<()>::new()).map_err(Into::into)
517 }
518}
519
520impl<T> Encode for [T] where T: Serialize {}
521impl<T> Encode for Vec<T> where T: Serialize {}
522
523macro_rules! impl_array {
524 ($($n:literal)+) => {
525 $(
526 #[allow(clippy::zero_prefixed_literal)]
527 impl<T> Encode for [T; $n] where T: Serialize {}
528 )+
529 }
530}
531
532impl_array! {
533 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
534 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
535}
536
537macro_rules! impl_tuple {
538 () => {};
539 ($h:ident $($t:ident)*) => {
540 impl<$h, $($t),*> Encode for ($h, $($t),*)
541 where
542 $h: Serialize,
543 $($t: Serialize,)*
544 {}
545
546 impl_tuple! { $($t)* }
547 }
548}
549
550impl_tuple! { A B C D E F G H I J K L M N O P }
551
552#[derive(Clone, PartialEq, Eq)]
558pub struct TupleBuffer(
559 Vec<u8>,
572);
573
574impl TupleBuffer {
575 #[inline(always)]
577 pub fn as_ptr(&self) -> *const u8 {
578 self.0.as_ptr()
579 }
580
581 #[inline(always)]
583 pub fn len(&self) -> usize {
584 self.0.len()
585 }
586
587 #[inline(always)]
588 pub fn is_empty(&self) -> bool {
589 self.0.is_empty()
590 }
591
592 #[track_caller]
595 #[inline(always)]
596 pub unsafe fn from_vec_unchecked(buf: Vec<u8>) -> Self {
597 Self(buf)
598 }
599
600 #[inline]
601 pub fn try_from_vec(data: Vec<u8>) -> Result<Self> {
602 let data = validate_msgpack(data)?;
603 unsafe { Ok(Self::from_vec_unchecked(data)) }
604 }
605}
606
607impl AsRef<[u8]> for TupleBuffer {
608 #[inline(always)]
609 fn as_ref(&self) -> &[u8] {
610 self.0.as_ref()
611 }
612}
613
614impl From<TupleBuffer> for Vec<u8> {
615 #[inline(always)]
616 fn from(b: TupleBuffer) -> Self {
617 b.0
618 }
619}
620
621impl TryFrom<Vec<u8>> for TupleBuffer {
622 type Error = Error;
623
624 #[inline(always)]
625 fn try_from(data: Vec<u8>) -> Result<Self> {
626 Self::try_from_vec(data)
627 }
628}
629
630impl From<Tuple> for TupleBuffer {
631 #[inline(always)]
632 fn from(t: Tuple) -> Self {
633 Self(t.to_vec())
634 }
635}
636
637impl From<&Tuple> for TupleBuffer {
638 #[inline(always)]
639 fn from(t: &Tuple) -> Self {
640 Self(t.to_vec())
641 }
642}
643
644impl Debug for TupleBuffer {
645 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
646 if let Ok(v) = rmpv::Value::decode(&self.0) {
647 f.debug_tuple("TupleBuffer").field(&v).finish()
648 } else {
649 f.debug_tuple("TupleBuffer").field(&self.0).finish()
650 }
651 }
652}
653
654impl ToTupleBuffer for TupleBuffer {
655 #[inline(always)]
656 fn to_tuple_buffer(&self) -> Result<TupleBuffer> {
657 Ok(self.clone())
658 }
659
660 #[inline(always)]
661 fn tuple_data(&self) -> Option<&[u8]> {
662 Some(&self.0)
663 }
664
665 #[inline(always)]
666 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()> {
667 w.write_all(self.as_ref()).map_err(Into::into)
668 }
669}
670
671impl serde_bytes::Serialize for TupleBuffer {
672 #[inline(always)]
673 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
674 where
675 S: serde::Serializer,
676 {
677 serde_bytes::Serialize::serialize(&self.0, serializer)
678 }
679}
680
681impl<'de> serde_bytes::Deserialize<'de> for TupleBuffer {
682 #[inline]
683 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
684 where
685 D: serde::Deserializer<'de>,
686 {
687 let tmp: Vec<u8> = serde_bytes::Deserialize::deserialize(deserializer)?;
688 Self::try_from(tmp).map_err(serde::de::Error::custom)
689 }
690}
691
692pub struct TupleFormat {
701 inner: *mut ffi::BoxTupleFormat,
704}
705
706impl TupleFormat {
707 #[inline(always)]
708 pub fn as_ptr(&self) -> *mut ffi::BoxTupleFormat {
709 self.inner
710 }
711}
712
713impl Default for TupleFormat {
714 #[inline(always)]
715 fn default() -> Self {
716 TupleFormat {
717 inner: unsafe { ffi::box_tuple_format_default() },
718 }
719 }
720}
721
722impl Drop for TupleFormat {
723 fn drop(&mut self) {
724 unsafe {
726 if self.inner != ffi::box_tuple_format_default() {
727 ffi::box_tuple_format_unref(self.inner)
728 }
729 }
730 }
731}
732
733impl Debug for TupleFormat {
734 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
735 if self.inner == Self::default().inner {
736 f.write_str("TupleFormat::default()")
737 } else {
738 f.debug_tuple("TupleFormat").field(&self.inner).finish()
739 }
740 }
741}
742
743pub struct TupleIterator {
749 inner: *mut ffi::BoxTupleIterator,
750}
751
752impl Debug for TupleIterator {
753 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
754 f.debug_struct("TupleIterator")
755 .field("position", &self.position())
756 .finish()
757 }
758}
759
760impl TupleIterator {
761 #[inline(always)]
768 pub fn position(&self) -> u32 {
769 unsafe { ffi::box_tuple_position(self.inner) }
770 }
771
772 #[inline(always)]
774 pub fn rewind(&mut self) {
775 unsafe { ffi::box_tuple_rewind(self.inner) }
776 }
777
778 #[inline]
788 pub fn seek<'t, T>(&'t mut self, fieldno: u32) -> Result<Option<T>>
789 where
790 T: Decode<'t>,
791 {
792 unsafe { field_value_from_ptr(ffi::box_tuple_seek(self.inner, fieldno) as _) }
793 }
794
795 #[allow(clippy::should_implement_trait)]
805 #[inline]
806 pub fn next<'t, T>(&'t mut self) -> Result<Option<T>>
807 where
808 T: Decode<'t>,
809 {
810 unsafe { field_value_from_ptr(ffi::box_tuple_next(self.inner) as _) }
811 }
812
813 pub fn update(&mut self) {}
814}
815
816impl Drop for TupleIterator {
817 #[inline(always)]
818 fn drop(&mut self) {
819 unsafe { ffi::box_tuple_iterator_free(self.inner) }
820 }
821}
822
823impl TupleIterator {}
824
825crate::define_str_enum! {
830 pub enum FieldType {
831 Any = "any",
832 Unsigned = "unsigned",
833 String = "string",
834 Number = "number",
835 Double = "double",
836 Integer = "integer",
837 Boolean = "boolean",
838 Varbinary = "varbinary",
839 Scalar = "scalar",
840 Decimal = "decimal",
841 Uuid = "uuid",
842 Datetime = "datetime",
843 Array = "array",
844 Map = "map",
845 }
846}
847
848impl Default for FieldType {
849 #[inline(always)]
850 fn default() -> Self {
851 Self::Any
852 }
853}
854
855impl From<index::FieldType> for FieldType {
856 #[rustfmt::skip]
857 fn from(t: index::FieldType) -> Self {
858 match t {
859 index::FieldType::Unsigned => Self::Unsigned,
862 index::FieldType::String => Self::String,
863 index::FieldType::Number => Self::Number,
864 index::FieldType::Double => Self::Double,
865 index::FieldType::Integer => Self::Integer,
866 index::FieldType::Boolean => Self::Boolean,
867 index::FieldType::Varbinary => Self::Varbinary,
868 index::FieldType::Scalar => Self::Scalar,
869 index::FieldType::Decimal => Self::Decimal,
870 index::FieldType::Uuid => Self::Uuid,
871 index::FieldType::Datetime => Self::Datetime,
872 index::FieldType::Array => Self::Array,
873 }
874 }
875}
876
877#[derive(Debug)]
904pub struct KeyDef {
905 inner: NonNull<ffi::BoxKeyDef>,
906}
907
908#[derive(Default, Debug, PartialEq, Eq, Hash)]
909pub struct KeyDefPart<'a> {
910 pub field_no: u32,
911 pub field_type: FieldType,
912 pub collation: Option<Cow<'a, CStr>>,
913 pub is_nullable: bool,
914 pub path: Option<Cow<'a, CStr>>,
915}
916
917impl<'a> KeyDefPart<'a> {
918 fn as_tt(&self) -> ffi::box_key_part_def_t {
919 let flags = if self.is_nullable {
920 ffi::BoxKeyDefPartFlag::IS_NULLABLE.bits()
921 } else {
922 0
923 };
924 ffi::box_key_part_def_t {
925 meat: ffi::BoxKeyDefPart {
926 fieldno: self.field_no,
927 field_type: self.field_type.as_cstr().as_ptr(),
928 flags,
929 collation: self
930 .collation
931 .as_deref()
932 .map(CStr::as_ptr)
933 .unwrap_or(null()),
934 path: self.path.as_deref().map(CStr::as_ptr).unwrap_or(null()),
935 },
936 }
937 }
938
939 pub fn from_index_part(p: &'a index::Part<u32>) -> Self {
940 let collation = p.collation.as_deref().map(|s| {
941 CString::new(s)
942 .expect("it's your fault if you put '\0' in collation")
943 .into()
944 });
945 let path = p.path.as_deref().map(|s| {
946 CString::new(s)
947 .expect("it's your fault if you put '\0' in collation")
948 .into()
949 });
950 Self {
951 field_no: p.field,
952 field_type: p.r#type.map(From::from).unwrap_or(FieldType::Any),
953 is_nullable: p.is_nullable.unwrap_or(false),
954 collation,
955 path,
956 }
957 }
958}
959
960impl KeyDef {
961 #[inline]
966 pub fn new<'a>(parts: impl IntoIterator<Item = &'a KeyDefPart<'a>>) -> Result<Self> {
967 let mut tt_parts = parts.into_iter().map(KeyDefPart::as_tt).collect::<Vec<_>>();
968 let ptr = unsafe { ffi::box_key_def_new_v2(tt_parts.as_mut_ptr(), tt_parts.len() as _) };
969 let inner = NonNull::new(ptr).ok_or_else(TarantoolError::last)?;
970 Ok(KeyDef { inner })
971 }
972
973 #[inline(always)]
983 pub fn compare(&self, tuple_a: &Tuple, tuple_b: &Tuple) -> Ordering {
984 unsafe {
985 ffi::box_tuple_compare(
986 tuple_a.ptr.as_ptr(),
987 tuple_b.ptr.as_ptr(),
988 self.inner.as_ptr(),
989 )
990 .cmp(&0)
991 }
992 }
993
994 #[inline]
1004 pub fn compare_with_key<K>(&self, tuple: &Tuple, key: &K) -> Ordering
1005 where
1006 K: ToTupleBuffer + ?Sized,
1007 {
1008 let key_buf = key.to_tuple_buffer().unwrap();
1009 let key_buf_ptr = key_buf.as_ptr() as _;
1010 unsafe {
1011 ffi::box_tuple_compare_with_key(tuple.ptr.as_ptr(), key_buf_ptr, self.inner.as_ptr())
1012 .cmp(&0)
1013 }
1014 }
1015
1016 #[inline]
1028 pub fn validate_tuple(&self, tuple: &Tuple) -> Result<()> {
1029 let rc =
1031 unsafe { ffi::box_key_def_validate_tuple(self.inner.as_ptr(), tuple.ptr.as_ptr()) };
1032 if rc != 0 {
1033 return Err(TarantoolError::last().into());
1034 }
1035 Ok(())
1036 }
1037
1038 #[inline]
1041 pub fn extract_key(&self, tuple: &Tuple) -> Result<TupleBuffer> {
1042 self.validate_tuple(tuple)?;
1043 let res;
1044 unsafe {
1047 let used_before = ffi::box_region_used();
1048 let data = self.extract_key_raw(tuple, -1)?;
1049 res = TupleBuffer::from_vec_unchecked(data.into());
1050 ffi::box_region_truncate(used_before);
1051 }
1052 Ok(res)
1053 }
1054
1055 #[inline]
1066 pub unsafe fn extract_key_raw<'box_region>(
1067 &self,
1068 tuple: &Tuple,
1069 multikey_idx: i32,
1070 ) -> Result<&'box_region [u8]> {
1071 let slice;
1072 unsafe {
1074 let mut size = 0;
1075 let data = ffi::box_key_def_extract_key(
1076 self.inner.as_ptr(),
1077 tuple.ptr.as_ptr(),
1078 multikey_idx,
1079 &mut size,
1080 );
1081 if data.is_null() {
1082 return Err(TarantoolError::last().into());
1083 }
1084 slice = std::slice::from_raw_parts(data as _, size as _);
1085 }
1086 Ok(slice)
1087 }
1088
1089 #[cfg(feature = "picodata")]
1098 pub fn hash(&self, tuple: &Tuple) -> u32 {
1099 unsafe { ffi::box_tuple_hash(tuple.ptr.as_ptr(), self.inner.as_ptr()) }
1100 }
1101}
1102
1103impl Drop for KeyDef {
1104 #[inline(always)]
1105 fn drop(&mut self) {
1106 unsafe { ffi::box_key_def_delete(self.inner.as_ptr()) }
1107 }
1108}
1109
1110impl From<&index::Metadata<'_>> for KeyDef {
1111 #[inline(always)]
1112 fn from(meta: &index::Metadata<'_>) -> Self {
1113 meta.to_key_def()
1114 }
1115}
1116
1117unsafe fn field_value_from_ptr<'de, T>(field_ptr: *mut u8) -> Result<Option<T>>
1118where
1119 T: Decode<'de>,
1120{
1121 if field_ptr.is_null() {
1122 return Ok(None);
1123 }
1124
1125 let max_len = u32::MAX >> 1;
1129 let rough_slice = std::slice::from_raw_parts(field_ptr, max_len as _);
1130 let mut cursor = std::io::Cursor::new(rough_slice);
1131 let start = cursor.position() as usize;
1132 crate::msgpack::skip_value(&mut cursor)?;
1135 let value_range = start..(cursor.position() as usize);
1136 let rough_slice = cursor.into_inner();
1137 let value_slice = &rough_slice[value_range];
1138 Ok(Some(T::decode(value_slice)?))
1139}
1140
1141#[repr(C)]
1146#[derive(Debug)]
1147pub struct FunctionCtx {
1148 inner: *mut ffi::BoxFunctionCtx,
1149}
1150
1151impl FunctionCtx {
1152 #[inline]
1158 pub fn return_tuple(&self, tuple: &Tuple) -> Result<c_int> {
1159 let result = unsafe { ffi::box_return_tuple(self.inner, tuple.ptr.as_ptr()) };
1160 if result < 0 {
1161 Err(TarantoolError::last().into())
1162 } else {
1163 Ok(result)
1164 }
1165 }
1166
1167 #[inline]
1176 pub fn return_mp<T>(&self, value: &T) -> Result<c_int>
1177 where
1178 T: Serialize + ?Sized,
1179 {
1180 let buf = rmp_serde::to_vec_named(value)?;
1181 self.return_bytes(&buf)
1182 }
1183
1184 #[inline]
1194 pub fn return_bytes(&self, bytes: &[u8]) -> Result<c_int> {
1195 let Range { start, end } = bytes.as_ptr_range();
1196 let result = unsafe { ffi::box_return_mp(self.inner, start as _, end as _) };
1197
1198 if result < 0 {
1199 Err(TarantoolError::last().into())
1200 } else {
1201 Ok(result)
1202 }
1203 }
1204
1205 #[cfg(feature = "picodata")]
1206 #[inline]
1207 pub fn mut_port_c(&mut self) -> &mut PortC {
1208 unsafe {
1209 let mut ctx = NonNull::new_unchecked(self.inner);
1210 NonNull::new_unchecked(ctx.as_mut().port)
1211 .as_mut()
1212 .as_mut_port_c()
1213 }
1214 }
1215}
1216
1217#[repr(C)]
1222pub struct FunctionArgs {
1223 pub start: *const u8,
1224 pub end: *const u8,
1225}
1226
1227impl Debug for FunctionArgs {
1228 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1229 f.debug_tuple("FunctionArgs")
1230 .field(&Tuple::from(self))
1231 .finish()
1232 }
1233}
1234
1235impl From<FunctionArgs> for Tuple {
1236 #[inline(always)]
1237 fn from(args: FunctionArgs) -> Tuple {
1238 Tuple::from(&args)
1239 }
1240}
1241
1242impl From<&FunctionArgs> for Tuple {
1243 #[inline(always)]
1244 fn from(args: &FunctionArgs) -> Tuple {
1245 unsafe { Tuple::from_raw_data(args.start as _, args.end.offset_from(args.start) as _) }
1246 }
1247}
1248
1249impl FunctionArgs {
1250 #[inline(always)]
1252 pub fn decode<'a, T>(&'a self) -> Result<T>
1253 where
1254 T: Decode<'a>,
1255 {
1256 let slice = unsafe {
1257 std::slice::from_raw_parts(self.start, self.end.offset_from(self.start) as _)
1258 };
1259 T::decode(slice)
1260 }
1261}
1262
1263#[inline]
1268pub fn session_push<T>(value: &T) -> Result<()>
1269where
1270 T: ToTupleBuffer + ?Sized,
1271{
1272 let buf = value.to_tuple_buffer().unwrap();
1273 let buf_ptr = buf.as_ptr() as *const c_char;
1274 if unsafe { ffi::box_session_push(buf_ptr, buf_ptr.add(buf.len())) } < 0 {
1275 Err(TarantoolError::last().into())
1276 } else {
1277 Ok(())
1278 }
1279}
1280
1281#[inline]
1282fn validate_msgpack<T>(data: T) -> Result<T>
1283where
1284 T: AsRef<[u8]> + Into<Vec<u8>>,
1285{
1286 let mut slice = data.as_ref();
1287 let m = rmp::decode::read_marker(&mut slice)?;
1288 if !matches!(m, Marker::FixArray(_) | Marker::Array16 | Marker::Array32) {
1289 return Err(error::EncodeError::InvalidMP(data.into()).into());
1290 }
1291 Ok(data)
1292}
1293
1294impl<L> tlua::Push<L> for Tuple
1295where
1296 L: tlua::AsLua,
1297{
1298 type Err = tlua::Void;
1299
1300 #[inline(always)]
1301 fn push_to_lua(&self, lua: L) -> tlua::PushResult<L, Self> {
1302 unsafe {
1303 ffi::luaT_pushtuple(tlua::AsLua::as_lua(&lua), self.ptr.as_ptr());
1304 Ok(tlua::PushGuard::new(lua, 1))
1305 }
1306 }
1307}
1308
1309impl<L> tlua::PushOne<L> for Tuple where L: tlua::AsLua {}
1310
1311impl<L> tlua::PushInto<L> for Tuple
1312where
1313 L: tlua::AsLua,
1314{
1315 type Err = tlua::Void;
1316
1317 #[inline(always)]
1318 fn push_into_lua(self, lua: L) -> tlua::PushResult<L, Self> {
1319 unsafe {
1320 ffi::luaT_pushtuple(tlua::AsLua::as_lua(&lua), self.ptr.as_ptr());
1321 Ok(tlua::PushGuard::new(lua, 1))
1322 }
1323 }
1324}
1325
1326impl<L> tlua::PushOneInto<L> for Tuple where L: tlua::AsLua {}
1327
1328impl<L> tlua::LuaRead<L> for Tuple
1329where
1330 L: tlua::AsLua,
1331{
1332 fn lua_read_at_position(lua: L, index: std::num::NonZeroI32) -> tlua::ReadResult<Self, L> {
1333 let lua_ptr = tlua::AsLua::as_lua(&lua);
1334 let mut ptr = unsafe { ffi::luaT_istuple(lua_ptr, index.get()) };
1335 if ptr.is_null() {
1336 let format = TupleFormat::default();
1337 ptr = unsafe { ffi::luaT_tuple_new(lua_ptr, index.get(), format.inner) };
1338 }
1339 Self::try_from_ptr(ptr).ok_or_else(|| {
1340 let e = tlua::WrongType::info("reading tarantool tuple")
1341 .expected_type::<Self>()
1342 .actual_single_lua(&lua, index);
1343 (lua, e)
1344 })
1345 }
1346}
1347
1348impl<L> tlua::LuaRead<L> for TupleBuffer
1349where
1350 L: tlua::AsLua,
1351{
1352 fn lua_read_at_position(lua: L, index: std::num::NonZeroI32) -> tlua::ReadResult<Self, L> {
1353 unsafe {
1354 let svp = ffi::box_region_used();
1355 let lua_ptr = tlua::AsLua::as_lua(&lua);
1356 let ptr = ffi::luaT_istuple(lua_ptr, index.get());
1357 if let Some(tuple) = Tuple::try_from_ptr(ptr) {
1358 return Ok(Self::from(tuple));
1359 }
1360 let mut len = 0;
1361 let data = ffi::luaT_tuple_encode(lua_ptr, index.get(), &mut len);
1362 if data.is_null() {
1363 let e = tlua::WrongType::info("converting Lua value to tarantool tuple")
1364 .expected("msgpack array")
1365 .actual(format!("error: {}", TarantoolError::last().message()));
1366 return Err((lua, e));
1367 }
1368 let data = std::slice::from_raw_parts(data, len);
1369 let data = Vec::from(data);
1370 ffi::box_region_truncate(svp);
1371 Ok(Self::from_vec_unchecked(data))
1372 }
1373 }
1374}
1375
1376pub trait Decode<'de>: Sized {
1385 fn decode(data: &'de [u8]) -> Result<Self>;
1386}
1387
1388impl<'de, T> Decode<'de> for T
1389where
1390 T: serde::Deserialize<'de>,
1391{
1392 #[inline(always)]
1393 fn decode(data: &'de [u8]) -> Result<Self> {
1394 rmp_serde::from_slice(data).map_err(|e| Error::decode::<T>(e, data.into()))
1395 }
1396}
1397
1398impl Decode<'_> for Tuple {
1399 #[inline(always)]
1400 fn decode(data: &[u8]) -> Result<Self> {
1401 Self::try_from_slice(data)
1402 }
1403}
1404
1405pub trait DecodeOwned: for<'de> Decode<'de> {}
1413impl<T> DecodeOwned for T where T: for<'de> Decode<'de> {}
1414
1415#[derive(Debug)]
1433#[repr(transparent)]
1434pub struct RawBytes(pub [u8]);
1435
1436impl RawBytes {
1437 #[inline(always)]
1439 pub fn new(data: &[u8]) -> &Self {
1440 unsafe { &*(data as *const [u8] as *const RawBytes) }
1442 }
1443}
1444
1445impl<'a> From<&'a [u8]> for &'a RawBytes {
1446 #[inline(always)]
1447 fn from(data: &'a [u8]) -> Self {
1448 RawBytes::new(data)
1449 }
1450}
1451
1452impl<'de> Decode<'de> for &'de RawBytes {
1453 #[inline(always)]
1454 fn decode(data: &'de [u8]) -> Result<Self> {
1455 Ok(RawBytes::new(data))
1457 }
1458}
1459
1460impl ToTupleBuffer for RawBytes {
1461 #[inline(always)]
1462 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()> {
1463 let data = &**self;
1464 validate_msgpack(data)?;
1465 w.write_all(data).map_err(Into::into)
1466 }
1467
1468 #[inline(always)]
1469 fn tuple_data(&self) -> Option<&[u8]> {
1470 let data = &**self;
1471 validate_msgpack(data).ok()?;
1472 Some(data)
1473 }
1474}
1475
1476impl std::ops::Deref for RawBytes {
1477 type Target = [u8];
1478 #[inline(always)]
1479 fn deref(&self) -> &Self::Target {
1480 &self.0
1481 }
1482}
1483
1484impl std::borrow::ToOwned for RawBytes {
1485 type Owned = RawByteBuf;
1486 #[inline(always)]
1487 fn to_owned(&self) -> Self::Owned {
1488 self.0.to_vec().into()
1489 }
1490}
1491
1492#[derive(Debug, PartialEq, Eq, Clone)]
1505pub struct RawByteBuf(pub Vec<u8>);
1506
1507impl serde_bytes::Serialize for RawByteBuf {
1508 #[inline(always)]
1509 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1510 where
1511 S: serde::Serializer,
1512 {
1513 serde_bytes::Serialize::serialize(&self.0, serializer)
1514 }
1515}
1516
1517impl<'de> serde_bytes::Deserialize<'de> for RawByteBuf {
1518 #[inline(always)]
1519 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1520 where
1521 D: serde::Deserializer<'de>,
1522 {
1523 serde_bytes::Deserialize::deserialize(deserializer).map(Self)
1524 }
1525}
1526
1527impl From<Vec<u8>> for RawByteBuf {
1528 #[inline(always)]
1529 fn from(b: Vec<u8>) -> Self {
1530 Self(b)
1531 }
1532}
1533
1534impl Decode<'_> for RawByteBuf {
1535 #[inline(always)]
1536 fn decode(data: &[u8]) -> Result<Self> {
1537 Ok(Self(data.into()))
1539 }
1540}
1541
1542impl ToTupleBuffer for RawByteBuf {
1543 #[inline(always)]
1544 fn write_tuple_data(&self, w: &mut impl Write) -> Result<()> {
1545 let data = self.as_slice();
1546 validate_msgpack(data)?;
1547 w.write_all(data).map_err(Into::into)
1548 }
1549
1550 #[inline(always)]
1551 fn tuple_data(&self) -> Option<&[u8]> {
1552 let data = self.as_slice();
1553 validate_msgpack(data).ok()?;
1554 Some(data)
1555 }
1556}
1557
1558impl std::ops::Deref for RawByteBuf {
1559 type Target = Vec<u8>;
1560 #[inline(always)]
1561 fn deref(&self) -> &Self::Target {
1562 &self.0
1563 }
1564}
1565
1566impl std::ops::DerefMut for RawByteBuf {
1567 #[inline(always)]
1568 fn deref_mut(&mut self) -> &mut Self::Target {
1569 &mut self.0
1570 }
1571}
1572
1573impl std::borrow::Borrow<RawBytes> for RawByteBuf {
1574 #[inline(always)]
1575 fn borrow(&self) -> &RawBytes {
1576 RawBytes::new(self.0.as_slice())
1577 }
1578}
1579
1580#[cfg(feature = "picodata")]
1581mod picodata {
1582 use super::*;
1583 use crate::static_ref;
1584
1585 impl Tuple {
1590 #[deprecated = "did not find its use"]
1603 #[inline(always)]
1604 pub fn as_named_buffer(&self) -> Result<Vec<u8>> {
1605 crate::say_error!("Tuple::as_named_buffer is no longer supported");
1606 panic!("Tuple::as_named_buffer is no longer supported");
1607 }
1608
1609 #[inline]
1611 pub fn data(&self) -> &[u8] {
1612 unsafe {
1613 let tuple = self.ptr.as_ref();
1615 tuple.data()
1616 }
1617 }
1618 }
1619
1620 impl PartialEq for Tuple {
1621 #[inline]
1622 fn eq(&self, other: &Self) -> bool {
1623 if self.ptr == other.ptr {
1624 return true;
1625 }
1626
1627 if self.bsize() != other.bsize() {
1628 return false;
1629 }
1630
1631 self.data() == other.data()
1632 }
1633 }
1634
1635 impl serde_bytes::Serialize for Tuple {
1636 #[inline(always)]
1637 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1638 where
1639 S: serde::Serializer,
1640 {
1641 serde_bytes::Serialize::serialize(self.data(), serializer)
1642 }
1643 }
1644
1645 impl TupleFormat {
1650 #[inline]
1653 pub fn with_rust_allocator() -> &'static Self {
1654 static mut SINGLETON: Option<TupleFormat> = None;
1655
1656 if unsafe { static_ref!(mut SINGLETON) }.is_none() {
1658 unsafe {
1660 let inner = ffi::box_tuple_format_new(std::ptr::null_mut(), 0);
1661 (*inner).vtab.tuple_new = vtab_impl::tuple_new_rust_allocator;
1662 (*inner).vtab.tuple_delete = vtab_impl::tuple_delete_rust_allocator;
1663 SINGLETON = Some(Self { inner });
1664 }
1665 }
1666
1667 unsafe { static_ref!(const SINGLETON) }
1668 .as_ref()
1669 .expect("just made sure it's there")
1670 }
1671
1672 #[deprecated = "did not find its use"]
1679 pub fn name_count(&self) -> u32 {
1680 crate::say_error!("TupleFormat::name_count is no longer supported");
1681 panic!("TupleFormat::name_count is no longer supported");
1682 }
1683
1684 #[deprecated = "did not find its use"]
1691 pub fn names(&self) -> impl Iterator<Item = &str> {
1692 crate::say_error!("TupleFormat::names is no longer supported");
1693 (|| panic!("TupleFormat::names is no longer supported"))();
1698 Vec::new().into_iter()
1700 }
1701 }
1702}
1703
1704#[cfg(feature = "picodata")]
1709pub struct TupleBuilder {
1710 is_rust_allocated: bool,
1714 buffer: Vec<u8>,
1715}
1716
1717#[cfg(feature = "picodata")]
1718impl TupleBuilder {
1719 const TUPLE_HEADER_PADDING: &'static [u8] = &[0; std::mem::size_of::<ffi::BoxTuple>()];
1720
1721 #[inline(always)]
1726 pub fn rust_allocated() -> Self {
1727 Self {
1728 is_rust_allocated: true,
1729 buffer: Vec::new(),
1730 }
1731 }
1732
1733 #[inline(always)]
1734 pub fn buffer(&self) -> &[u8] {
1735 &self.buffer
1736 }
1737
1738 #[inline]
1742 pub fn reserve(&mut self, mut capacity: usize) {
1743 if self.is_rust_allocated && self.buffer.capacity() == 0 {
1744 capacity += std::mem::size_of::<ffi::BoxTuple>();
1745 }
1746 self.buffer.reserve(capacity);
1747 }
1748
1749 #[inline]
1750 pub fn append(&mut self, data: &[u8]) {
1751 if self.is_rust_allocated && self.buffer.is_empty() {
1752 if self.buffer.capacity() == 0 {
1753 self.buffer
1754 .reserve(Self::TUPLE_HEADER_PADDING.len() + data.len());
1755 }
1756 self.buffer.extend_from_slice(Self::TUPLE_HEADER_PADDING);
1757 }
1758 self.buffer.extend_from_slice(data);
1759 }
1760
1761 #[inline]
1762 pub fn into_tuple(self) -> Result<Tuple> {
1763 if self.is_rust_allocated {
1764 self.into_tuple_rust_allocated()
1765 } else {
1766 Tuple::try_from_slice(&self.buffer)
1767 }
1768 }
1769
1770 fn into_tuple_rust_allocated(self) -> Result<Tuple> {
1771 use crate::error::BoxError;
1772 use crate::error::TarantoolErrorCode;
1773
1774 if self.buffer.is_empty() {
1775 #[rustfmt::skip]
1776 return Err(BoxError::new(TarantoolErrorCode::IllegalParams, "cannot construct an empty tuple").into());
1777 }
1778
1779 if self.buffer.len() < Self::TUPLE_HEADER_PADDING.len() {
1780 #[rustfmt::skip]
1781 return Err(BoxError::new(TarantoolErrorCode::IllegalParams, "buffer is corrupted").into());
1782 }
1783
1784 let mut tuple_chunk = self.buffer;
1785 let data_offset = Self::TUPLE_HEADER_PADDING.len();
1786 let data_len = tuple_chunk.len() - data_offset;
1787 validate_msgpack(&tuple_chunk[data_offset..])?;
1788
1789 let format = TupleFormat::with_rust_allocator();
1790
1791 let tuple = tuple_chunk.as_mut_ptr().cast::<ffi::BoxTuple>();
1792 unsafe {
1793 std::ptr::write(
1794 tuple,
1795 ffi::BoxTuple {
1797 refs: 0,
1798 flags: 0,
1799 format_id: (*format.inner).id,
1800 data_offset: data_offset as _,
1801 bsize: data_len as _,
1802 },
1803 );
1804 }
1805 unsafe {
1807 ffi::box_tuple_format_ref(format.inner);
1808 }
1809
1810 _ = Box::into_raw(tuple_chunk.into_boxed_slice());
1812
1813 let tuple = unsafe { NonNull::new_unchecked(tuple) };
1815 let tuple = Tuple::from_ptr(tuple);
1816 return Ok(tuple);
1817 }
1818}
1819
1820#[cfg(feature = "picodata")]
1821impl std::io::Write for TupleBuilder {
1822 #[inline(always)]
1823 fn write(&mut self, data: &[u8]) -> std::io::Result<usize> {
1824 self.append(data);
1825 Ok(data.len())
1826 }
1827
1828 #[inline(always)]
1829 fn flush(&mut self) -> std::io::Result<()> {
1830 Ok(())
1831 }
1832}
1833
1834#[cfg(feature = "picodata")]
1839mod vtab_impl {
1840 use super::*;
1841
1842 pub unsafe extern "C" fn tuple_new_rust_allocator(
1844 format: *mut ffi::BoxTupleFormat,
1845 data: *const u8,
1846 end: *const u8,
1847 ) -> *mut ffi::BoxTuple {
1848 const TUPLE_HEADER_SIZE: usize = std::mem::size_of::<ffi::BoxTuple>();
1849 let data_offset = TUPLE_HEADER_SIZE;
1850 let data_len = end.offset_from(data);
1853 debug_assert!(data_len >= 0);
1854 let data_len = data_len as usize;
1855 debug_assert!(data_len <= u32::MAX as usize);
1856
1857 let total_size = data_offset + data_len;
1859 let mut tuple_chunk: Vec<u8> = Vec::with_capacity(total_size);
1860
1861 let tuple = tuple_chunk.as_mut_ptr().cast::<ffi::BoxTuple>();
1862 std::ptr::write(
1863 tuple,
1864 ffi::BoxTuple {
1866 refs: 0,
1867 flags: 0,
1868 format_id: (*format).id,
1869 data_offset: data_offset as _,
1870 bsize: data_len as _,
1871 },
1872 );
1873 ffi::box_tuple_format_ref(format);
1874
1875 let data_slice = std::slice::from_raw_parts(data, data_len);
1876 tuple_chunk.set_len(total_size);
1877 let tuple_data = &mut tuple_chunk[data_offset..];
1878 debug_assert_eq!(data_slice.len(), tuple_data.len());
1879 tuple_data.copy_from_slice(data_slice);
1880
1881 let tuple_chunk: Box<[u8]> = tuple_chunk.into_boxed_slice();
1883 _ = Box::into_raw(tuple_chunk);
1884
1885 return tuple;
1886 }
1887
1888 pub unsafe extern "C" fn tuple_delete_rust_allocator(
1890 format: *mut ffi::BoxTupleFormat,
1891 tuple: *mut ffi::BoxTuple,
1892 ) {
1893 debug_assert!(tuple != 0 as _);
1894 debug_assert_eq!((*tuple).refs, 0);
1895 const FLAG_TUPLE_HAS_UPLOADED_REFS: u8 = 1 << 0;
1896 debug_assert_eq!(((*tuple).flags & FLAG_TUPLE_HAS_UPLOADED_REFS), 0);
1897
1898 ffi::box_tuple_format_unref(format);
1899
1900 let total_size = (*tuple).data_offset() as usize + (*tuple).bsize();
1901
1902 let tuple_chunk_start = tuple.cast::<u8>();
1903 let tuple_chunk_slice = std::slice::from_raw_parts_mut(tuple_chunk_start, total_size);
1904 let tuple_chunk: Box<[u8]> = Box::from_raw(tuple_chunk_slice);
1906 drop(tuple_chunk);
1907 }
1908}
1909
1910#[cfg(feature = "internal_test")]
1911mod test {
1912 #![allow(clippy::redundant_clone)]
1913 use super::*;
1914 use crate::space;
1915 use crate::space::Space;
1916 use pretty_assertions::assert_eq;
1917
1918 #[crate::test(tarantool = "crate")]
1919 fn tuple_buffer_from_lua() {
1920 let svp = unsafe { ffi::box_region_used() };
1921
1922 let lua = crate::lua_state();
1923 let t: TupleBuffer = lua
1924 .eval("return { 3, 'foo', { true, box.NIL, false } }")
1925 .unwrap();
1926
1927 #[derive(::serde::Deserialize, PartialEq, Eq, Debug)]
1928 struct S {
1929 i: i32,
1930 s: String,
1931 t: [Option<bool>; 3],
1932 }
1933
1934 let s = S::decode(t.as_ref()).unwrap();
1935 assert_eq!(
1936 s,
1937 S {
1938 i: 3,
1939 s: "foo".into(),
1940 t: [Some(true), None, Some(false)]
1941 }
1942 );
1943
1944 let res = lua.eval::<TupleBuffer>("return 1, 2, 3");
1945 assert_eq!(
1946 res.unwrap_err().to_string(),
1947 "failed converting Lua value to tarantool tuple: msgpack array expected, got error: A tuple or a table expected, got number
1948 while reading value(s) returned by Lua: tarantool::tuple::TupleBuffer expected, got (number, number, number)"
1949 );
1950
1951 let res = lua.eval::<TupleBuffer>("return { 1, 2, foo = 'bar' }");
1952 assert_eq!(
1953 res.unwrap_err().to_string(),
1954 "failed converting Lua value to tarantool tuple: msgpack array expected, got error: Tuple/Key must be MsgPack array
1955 while reading value(s) returned by Lua: tarantool::tuple::TupleBuffer expected, got table"
1956 );
1957
1958 let res = lua.eval::<TupleBuffer>(
1959 "ffi = require 'ffi';
1960 local cdata = ffi.new('struct { int x; int y; }', { x = -1, y = 2 })
1961 return { 1, cdata }",
1962 );
1963 assert_eq!(
1964 res.unwrap_err().to_string(),
1965 "failed converting Lua value to tarantool tuple: msgpack array expected, got error: unsupported Lua type 'cdata'
1966 while reading value(s) returned by Lua: tarantool::tuple::TupleBuffer expected, got table"
1967 );
1968
1969 assert_eq!(svp, unsafe { ffi::box_region_used() });
1970 }
1971
1972 #[crate::test(tarantool = "crate")]
1973 fn decode_error() {
1974 use super::*;
1975
1976 let buf = (1, 2, 3).to_tuple_buffer().unwrap();
1977 let err = <(String, String)>::decode(buf.as_ref()).unwrap_err();
1978 assert_eq!(
1979 err.to_string(),
1980 r#"failed to decode tuple: invalid type: integer `1`, expected a string when decoding msgpack b"\x93\x01\x02\x03" into rust type (alloc::string::String, alloc::string::String)"#
1981 );
1982
1983 let buf = ("hello", [1, 2, 3], "goodbye").to_tuple_buffer().unwrap();
1984 let err = <(String, (i32, String, i32), String)>::decode(buf.as_ref()).unwrap_err();
1985 assert_eq!(
1986 err.to_string(),
1987 r#"failed to decode tuple: invalid type: integer `2`, expected a string when decoding msgpack b"\x93\xa5hello\x93\x01\x02\x03\xa7goodbye" into rust type (alloc::string::String, (i32, alloc::string::String, i32), alloc::string::String)"#
1988 )
1989 }
1990
1991 #[crate::test(tarantool = "crate")]
1992 fn key_def_extract_key() {
1993 let space = Space::builder(&crate::temp_space_name!())
1994 .field(("id", space::FieldType::Unsigned))
1995 .field(("not-key", space::FieldType::Array))
1996 .field(("s", space::FieldType::String))
1997 .field(("nested", space::FieldType::Any))
1998 .create()
1999 .unwrap();
2000
2001 let index = space
2002 .index_builder("pk")
2003 .part("id")
2004 .part("s")
2005 .part(
2006 index::Part::<String>::field("nested")
2007 .field_type(index::FieldType::Unsigned)
2008 .path("[2].blabla"),
2009 )
2010 .create()
2011 .unwrap();
2012
2013 let key_def = index.meta().unwrap().to_key_def();
2014
2015 let tuple = Tuple::new(&["foo"]).unwrap();
2016 let e = key_def.extract_key(&tuple).unwrap_err();
2017 assert_eq!(e.to_string(), "box error: KeyPartType: Supplied key type of part 0 does not match index part type: expected unsigned");
2018
2019 let tuple = Tuple::new(&[1]).unwrap();
2020 let e = key_def.extract_key(&tuple).unwrap_err();
2021 assert_eq!(
2025 e.to_string(),
2026 "box error: FieldMissing: Tuple field [3] required by space format is missing"
2027 );
2028
2029 let tuple = Tuple::new(&(1, [1, 2, 3], "foo")).unwrap();
2030 let e = key_def.extract_key(&tuple).unwrap_err();
2031 assert_eq!(
2032 e.to_string(),
2033 "box error: FieldMissing: Tuple field [4][2].blabla required by space format is missing"
2034 );
2035
2036 let raw_data = b"\x94\x69\x93\x01\x02\x03\xa3foo\x93\xc0\x81\xa6blabla\x42\x07"; let tuple = Tuple::new(RawBytes::new(raw_data)).unwrap();
2038 let key = key_def.extract_key(&tuple).unwrap();
2039 assert_eq!(key.as_ref(), b"\x93\x69\xa3foo\x42"); let raw_data = b"\x94\x13\xa9not-array\xa3bar\x92\xc0\x81\xa6blabla\x37"; let tuple = Tuple::new(RawBytes::new(raw_data)).unwrap();
2047 let key = key_def.extract_key(&tuple).unwrap();
2048 assert_eq!(key.as_ref(), b"\x93\x13\xa3bar\x37");
2049
2050 let e = space.insert(&tuple).unwrap_err();
2052 assert_eq!(e.to_string(), "box error: FieldType: Tuple field 2 (not-key) type does not match one required by operation: expected array, got string");
2053 }
2054
2055 #[cfg(feature = "picodata")]
2056 #[crate::test(tarantool = "crate")]
2057 fn tuple_data() {
2058 let tuple = Tuple::new(&(69, "nice", [3, 2, 1])).unwrap();
2060 assert_eq!(tuple.data(), b"\x93\x45\xa4nice\x93\x03\x02\x01");
2065
2066 let space = Space::builder(&crate::temp_space_name!())
2068 .field(("id", space::FieldType::Unsigned))
2069 .field(("name", space::FieldType::String))
2070 .create()
2071 .unwrap();
2072
2073 space.index_builder("pk").create().unwrap();
2074
2075 let tuple = space.insert(&(13, "37")).unwrap();
2076 assert_eq!(tuple.data(), b"\x92\x0d\xa237");
2077 }
2078
2079 #[cfg(feature = "picodata")]
2080 #[crate::test(tarantool = "crate")]
2081 fn compare_tuples() {
2082 let data = b"\x92\xa3foo\xa3bar";
2085 let tuple_1 = Tuple::try_from_slice(data).unwrap();
2086
2087 let tuple_1_clone = tuple_1.clone();
2089 assert_eq!(tuple_1_clone.as_ptr(), tuple_1.as_ptr());
2090 assert_eq!(tuple_1_clone, tuple_1);
2091
2092 let tuple_1_equivalent = Tuple::try_from_slice(data).unwrap();
2094 assert_ne!(tuple_1_equivalent.as_ptr(), tuple_1.as_ptr());
2095 assert_eq!(tuple_1_equivalent, tuple_1);
2096
2097 let other_data = b"\x93\x10\x20\x30";
2101 let tuple_2 = Tuple::try_from_slice(other_data).unwrap();
2102 assert_ne!(data.len(), other_data.len());
2103 assert_ne!(tuple_1, tuple_2);
2104
2105 let other_data_same_len = b"\x92\xa3foo\xa3baz";
2109 assert_eq!(data.len(), other_data_same_len.len());
2110 let tuple_3 = Tuple::try_from_slice(other_data_same_len).unwrap();
2111 assert_ne!(tuple_2, tuple_3);
2112 }
2113
2114 #[cfg(feature = "picodata")]
2115 #[crate::test(tarantool = "crate")]
2116 fn serialize_deserialize() {
2117 #[derive(Debug, serde::Serialize, serde::Deserialize)]
2118 struct Wrapper {
2119 #[serde(with = "serde_bytes")]
2120 tuple: Tuple,
2121 }
2122
2123 let data = rmp_serde::to_vec_named(&Wrapper {
2125 tuple: Tuple::new(&(0x77, "hello", 0x77)).unwrap(),
2126 })
2127 .unwrap();
2128 assert_eq!(&data, b"\x81\xa5tuple\xc4\x09\x93\x77\xa5hello\x77");
2133
2134 let data = b"\x81\xa5tuple\xc4\x0c\x94\xa7numbers\x03\x01\x04";
2137 let w: Wrapper = rmp_serde::from_slice(data).unwrap();
2138 let s: &str = w.tuple.field(0).unwrap().unwrap();
2139 assert_eq!(s, "numbers");
2140 let n: i32 = w.tuple.field(1).unwrap().unwrap();
2141 assert_eq!(n, 3);
2142 let n: i32 = w.tuple.field(2).unwrap().unwrap();
2143 assert_eq!(n, 1);
2144 let n: i32 = w.tuple.field(3).unwrap().unwrap();
2145 assert_eq!(n, 4);
2146
2147 let data = b"\x81\xa5tuple\xc4\x01\x45";
2149 let e = rmp_serde::from_slice::<Wrapper>(data).unwrap_err();
2150 assert_eq!(e.to_string(), "failed to encode tuple: invalid msgpack value (expected array, found Integer(PosInt(69)))");
2151 }
2152
2153 #[cfg(feature = "picodata")]
2154 #[crate::test(tarantool = "crate")]
2155 fn rust_allocated_tuples() {
2156 let mut builder = TupleBuilder::rust_allocated();
2157 builder.append(b"\x91");
2159 builder.append(b"\xc4\x10");
2161 builder.append(b"0123456789abcdef");
2162 let tuple = builder.into_tuple().unwrap();
2163
2164 assert_eq!(tuple.len(), 1);
2166 assert_eq!(tuple.bsize(), 19);
2167 assert_eq!(tuple.data(), b"\x91\xc4\x100123456789abcdef");
2168 assert_eq!(tuple.to_vec(), b"\x91\xc4\x100123456789abcdef");
2169
2170 let (value,): (serde_bytes::ByteBuf,) = tuple.decode().unwrap();
2171 assert_eq!(value, b"0123456789abcdef");
2172
2173 let value: &serde_bytes::Bytes = tuple.field(0).unwrap().unwrap();
2174 assert_eq!(value, b"0123456789abcdef");
2175
2176 let mut iter = tuple.iter().unwrap();
2177 let value: &serde_bytes::Bytes = iter.next().unwrap().unwrap();
2178 assert_eq!(value, b"0123456789abcdef");
2179 assert_eq!(iter.next::<()>().unwrap(), None);
2180
2181 #[rustfmt::skip]
2182 assert_eq!(tuple.format().as_ptr(), TupleFormat::with_rust_allocator().as_ptr());
2183
2184 let mut builder = TupleBuilder::rust_allocated();
2186 builder.append(b"\xa1!");
2188 let e = builder.into_tuple().unwrap_err();
2189 assert_eq!(e.to_string(), "failed to encode tuple: invalid msgpack value (expected array, found String(Utf8String { s: Ok(\"!\") }))");
2190
2191 let mut builder = TupleBuilder::rust_allocated();
2193 builder.reserve(4);
2194 builder.append(b"\x93");
2195 builder.append(b"\x01");
2196 builder.append(b"\x02");
2197 builder.append(b"\x03");
2198 let tuple = builder.into_tuple().unwrap();
2199 let value: (i32, i32, i32) = tuple.decode().unwrap();
2200 assert_eq!(value, (1, 2, 3));
2201
2202 let mut builder = TupleBuilder::rust_allocated();
2204 builder.reserve(0);
2205 builder.append(b"\x91");
2206 builder.append(b"\xa5");
2207 builder.append(b"hell");
2208 builder.append(b"o");
2209 let tuple = builder.into_tuple().unwrap();
2210 let (value,): (String,) = tuple.decode().unwrap();
2211 assert_eq!(value, "hello");
2212
2213 let mut builder = TupleBuilder::rust_allocated();
2215 rmp_serde::encode::write(&mut builder, &(1, "two", 3.14)).unwrap();
2216 let tuple = builder.into_tuple().unwrap();
2217 let value: (i32, String, f32) = tuple.decode().unwrap();
2218 assert_eq!(value, (1, "two".to_owned(), 3.14));
2219 }
2220
2221 #[cfg(feature = "picodata")]
2222 #[crate::test(tarantool = "crate")]
2223 fn tuple_format_no_use_after_free() {
2224 let mut builder = TupleBuilder::rust_allocated();
2225 builder.append(b"\x90");
2227 let tuple = builder.into_tuple().unwrap();
2228
2229 let original_ref_count = unsafe { (*TupleFormat::with_rust_allocator().as_ptr()).refs };
2230 assert!(original_ref_count > 0);
2231
2232 let f1 = tuple.format();
2233
2234 let ref_count = unsafe { (*TupleFormat::with_rust_allocator().as_ptr()).refs };
2239 assert_eq!(ref_count, original_ref_count + 1);
2240
2241 let f2 = tuple.format();
2242
2243 let ref_count = unsafe { (*TupleFormat::with_rust_allocator().as_ptr()).refs };
2244 assert_eq!(ref_count, original_ref_count + 2);
2245
2246 drop(f1);
2247
2248 let ref_count = unsafe { (*TupleFormat::with_rust_allocator().as_ptr()).refs };
2249 assert_eq!(ref_count, original_ref_count + 1);
2250
2251 drop(f2);
2252
2253 let ref_count = unsafe { (*TupleFormat::with_rust_allocator().as_ptr()).refs };
2254 assert_eq!(ref_count, original_ref_count);
2255 }
2256}