1use std::os::raw::c_char;
11use std::ptr::null_mut;
12
13use num_traits::ToPrimitive;
14
15use crate::error::{Error, TarantoolError};
16use crate::tuple::{ffi::BoxTuple, AsTuple, Tuple, TupleBuffer};
17
18pub struct Index {
20 space_id: u32,
21 index_id: u32,
22}
23
24#[repr(i32)]
42#[derive(Debug, Copy, Clone, ToPrimitive)]
43pub enum IteratorType {
44 Eq = 0,
46
47 Req = 1,
49
50 All = 2,
52
53 LT = 3,
55
56 LE = 4,
58
59 GE = 5,
61
62 GT = 6,
64
65 BitsAllSet = 7,
67
68 BitsAnySet = 8,
70
71 BitsAllNotSet = 9,
73
74 Ovelaps = 10,
76
77 Neigbor = 11,
79}
80
81impl Index {
82 pub(crate) fn new(space_id: u32, index_id: u32) -> Self {
83 Index { space_id, index_id }
84 }
85
86 pub fn get<K>(&self, key: &K) -> Result<Option<Tuple>, Error>
94 where
95 K: AsTuple,
96 {
97 let key_buf = key.serialize_as_tuple().unwrap();
98 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
99 let mut result_ptr = null_mut::<BoxTuple>();
100
101 if unsafe {
102 ffi::box_index_get(
103 self.space_id,
104 self.index_id,
105 key_buf_ptr,
106 key_buf_ptr.offset(key_buf.len() as isize),
107 &mut result_ptr,
108 )
109 } < 0
110 {
111 return Err(TarantoolError::last().into());
112 }
113
114 Ok(if result_ptr.is_null() {
115 None
116 } else {
117 Some(Tuple::from_ptr(result_ptr))
118 })
119 }
120
121 pub fn select<K>(&self, iterator_type: IteratorType, key: &K) -> Result<IndexIterator, Error>
129 where
130 K: AsTuple,
131 {
132 let key_buf = key.serialize_as_tuple().unwrap();
133 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
134
135 let ptr = unsafe {
136 ffi::box_index_iterator(
137 self.space_id,
138 self.index_id,
139 iterator_type.to_i32().unwrap(),
140 key_buf_ptr,
141 key_buf_ptr.offset(key_buf.len() as isize),
142 )
143 };
144
145 if ptr.is_null() {
146 return Err(TarantoolError::last().into());
147 }
148
149 Ok(IndexIterator {
150 ptr,
151 _key_data: key_buf,
152 })
153 }
154
155 pub fn delete<K>(&mut self, key: &K) -> Result<Option<Tuple>, Error>
164 where
165 K: AsTuple,
166 {
167 let key_buf = key.serialize_as_tuple().unwrap();
168 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
169 let mut result_ptr = null_mut::<BoxTuple>();
170
171 if unsafe {
172 ffi::box_delete(
173 self.space_id,
174 self.index_id,
175 key_buf_ptr,
176 key_buf_ptr.offset(key_buf.len() as isize),
177 &mut result_ptr,
178 )
179 } < 0
180 {
181 return Err(TarantoolError::last().into());
182 }
183
184 Ok(if result_ptr.is_null() {
185 None
186 } else {
187 Some(Tuple::from_ptr(result_ptr))
188 })
189 }
190
191 pub fn update<K, Op>(&mut self, key: &K, ops: &Vec<Op>) -> Result<Option<Tuple>, Error>
203 where
204 K: AsTuple,
205 Op: AsTuple,
206 {
207 let key_buf = key.serialize_as_tuple().unwrap();
208 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
209 let ops_buf = ops.serialize_as_tuple().unwrap();
210 let ops_buf_ptr = ops_buf.as_ptr() as *const c_char;
211 let mut result_ptr = null_mut::<BoxTuple>();
212
213 if unsafe {
214 ffi::box_update(
215 self.space_id,
216 self.index_id,
217 key_buf_ptr,
218 key_buf_ptr.offset(key_buf.len() as isize),
219 ops_buf_ptr,
220 ops_buf_ptr.offset(ops_buf.len() as isize),
221 0,
222 &mut result_ptr,
223 )
224 } < 0
225 {
226 return Err(TarantoolError::last().into());
227 }
228
229 Ok(if result_ptr.is_null() {
230 None
231 } else {
232 Some(Tuple::from_ptr(result_ptr))
233 })
234 }
235
236 pub fn upsert<T, Op>(&mut self, value: &T, ops: &Vec<Op>) -> Result<Option<Tuple>, Error>
247 where
248 T: AsTuple,
249 Op: AsTuple,
250 {
251 let value_buf = value.serialize_as_tuple().unwrap();
252 let value_buf_ptr = value_buf.as_ptr() as *const c_char;
253 let ops_buf = ops.serialize_as_tuple().unwrap();
254 let ops_buf_ptr = ops_buf.as_ptr() as *const c_char;
255 let mut result_ptr = null_mut::<BoxTuple>();
256
257 if unsafe {
258 ffi::box_upsert(
259 self.space_id,
260 self.index_id,
261 value_buf_ptr,
262 value_buf_ptr.offset(value_buf.len() as isize),
263 ops_buf_ptr,
264 ops_buf_ptr.offset(ops_buf.len() as isize),
265 0,
266 &mut result_ptr,
267 )
268 } < 0
269 {
270 return Err(TarantoolError::last().into());
271 }
272
273 Ok(if result_ptr.is_null() {
274 None
275 } else {
276 Some(Tuple::from_ptr(result_ptr))
277 })
278 }
279
280 pub fn len(&self) -> Result<usize, Error> {
282 let result = unsafe { ffi::box_index_len(self.space_id, self.index_id) };
283
284 if result < 0 {
285 Err(TarantoolError::last().into())
286 } else {
287 Ok(result as usize)
288 }
289 }
290
291 pub fn bsize(&self) -> Result<usize, Error> {
293 let result = unsafe { ffi::box_index_bsize(self.space_id, self.index_id) };
294
295 if result < 0 {
296 Err(TarantoolError::last().into())
297 } else {
298 Ok(result as usize)
299 }
300 }
301
302 pub fn random(&self, seed: u32) -> Result<Option<Tuple>, Error> {
306 let mut result_ptr = null_mut::<BoxTuple>();
307 if unsafe { ffi::box_index_random(self.space_id, self.index_id, seed, &mut result_ptr) } < 0
308 {
309 return Err(TarantoolError::last().into());
310 }
311
312 Ok(if result_ptr.is_null() {
313 None
314 } else {
315 Some(Tuple::from_ptr(result_ptr))
316 })
317 }
318
319 pub fn min<K>(&self, key: &K) -> Result<Option<Tuple>, Error>
325 where
326 K: AsTuple,
327 {
328 let key_buf = key.serialize_as_tuple().unwrap();
329 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
330 let mut result_ptr = null_mut::<BoxTuple>();
331
332 if unsafe {
333 ffi::box_index_min(
334 self.space_id,
335 self.index_id,
336 key_buf_ptr,
337 key_buf_ptr.offset(key_buf.len() as isize),
338 &mut result_ptr,
339 )
340 } < 0
341 {
342 return Err(TarantoolError::last().into());
343 }
344
345 Ok(if result_ptr.is_null() {
346 None
347 } else {
348 Some(Tuple::from_ptr(result_ptr))
349 })
350 }
351
352 pub fn max<K>(&self, key: &K) -> Result<Option<Tuple>, Error>
358 where
359 K: AsTuple,
360 {
361 let key_buf = key.serialize_as_tuple().unwrap();
362 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
363 let mut result_ptr = null_mut::<BoxTuple>();
364
365 if unsafe {
366 ffi::box_index_max(
367 self.space_id,
368 self.index_id,
369 key_buf_ptr,
370 key_buf_ptr.offset(key_buf.len() as isize),
371 &mut result_ptr,
372 )
373 } < 0
374 {
375 return Err(TarantoolError::last().into());
376 }
377
378 Ok(if result_ptr.is_null() {
379 None
380 } else {
381 Some(Tuple::from_ptr(result_ptr))
382 })
383 }
384
385 pub fn count<K>(&self, iterator_type: IteratorType, key: &K) -> Result<usize, Error>
390 where
391 K: AsTuple,
392 {
393 let key_buf = key.serialize_as_tuple().unwrap();
394 let key_buf_ptr = key_buf.as_ptr() as *const c_char;
395
396 let result = unsafe {
397 ffi::box_index_count(
398 self.space_id,
399 self.index_id,
400 iterator_type.to_i32().unwrap(),
401 key_buf_ptr,
402 key_buf_ptr.offset(key_buf.len() as isize),
403 )
404 };
405
406 if result < 0 {
407 Err(TarantoolError::last().into())
408 } else {
409 Ok(result as usize)
410 }
411 }
412
413 pub fn extract_key(&self, tuple: Tuple) -> Tuple {
419 let mut result_size: u32 = 0;
420 let result_ptr = unsafe {
421 ffi::box_tuple_extract_key(
422 tuple.into_ptr(),
423 self.space_id,
424 self.index_id,
425 &mut result_size,
426 )
427 };
428 Tuple::from_raw_data(result_ptr, result_size)
429 }
430}
431
432pub struct IndexIterator {
434 ptr: *mut ffi::BoxIterator,
435 _key_data: TupleBuffer,
436}
437
438impl Iterator for IndexIterator {
439 type Item = Tuple;
440
441 fn next(&mut self) -> Option<Self::Item> {
442 let mut result_ptr = null_mut::<BoxTuple>();
443 if unsafe { ffi::box_iterator_next(self.ptr, &mut result_ptr) } < 0 {
444 return None;
445 }
446
447 if result_ptr.is_null() {
448 None
449 } else {
450 Some(Tuple::from_ptr(result_ptr))
451 }
452 }
453}
454
455impl Drop for IndexIterator {
456 fn drop(&mut self) {
457 unsafe { ffi::box_iterator_free(self.ptr) };
458 }
459}
460
461mod ffi {
462 use std::os::raw::{c_char, c_int};
463
464 use crate::tuple::ffi::BoxTuple;
465
466 #[repr(C)]
467 pub struct BoxIterator {
468 _unused: [u8; 0],
469 }
470
471 extern "C" {
472 pub fn box_index_iterator(
473 space_id: u32,
474 index_id: u32,
475 type_: c_int,
476 key: *const c_char,
477 key_end: *const c_char,
478 ) -> *mut BoxIterator;
479
480 pub fn box_iterator_next(iterator: *mut BoxIterator, result: *mut *mut BoxTuple) -> c_int;
481 pub fn box_iterator_free(iterator: *mut BoxIterator);
482 pub fn box_index_len(space_id: u32, index_id: u32) -> isize;
483 pub fn box_index_bsize(space_id: u32, index_id: u32) -> isize;
484 pub fn box_index_random(
485 space_id: u32,
486 index_id: u32,
487 rnd: u32,
488 result: *mut *mut BoxTuple,
489 ) -> c_int;
490
491 pub fn box_index_get(
492 space_id: u32,
493 index_id: u32,
494 key: *const c_char,
495 key_end: *const c_char,
496 result: *mut *mut BoxTuple,
497 ) -> c_int;
498
499 pub fn box_index_min(
500 space_id: u32,
501 index_id: u32,
502 key: *const c_char,
503 key_end: *const c_char,
504 result: *mut *mut BoxTuple,
505 ) -> c_int;
506
507 pub fn box_index_max(
508 space_id: u32,
509 index_id: u32,
510 key: *const c_char,
511 key_end: *const c_char,
512 result: *mut *mut BoxTuple,
513 ) -> c_int;
514
515 pub fn box_index_count(
516 space_id: u32,
517 index_id: u32,
518 type_: c_int,
519 key: *const c_char,
520 key_end: *const c_char,
521 ) -> isize;
522
523 pub fn box_delete(
524 space_id: u32,
525 index_id: u32,
526 key: *const c_char,
527 key_end: *const c_char,
528 result: *mut *mut BoxTuple,
529 ) -> c_int;
530
531 pub fn box_update(
532 space_id: u32,
533 index_id: u32,
534 key: *const c_char,
535 key_end: *const c_char,
536 ops: *const c_char,
537 ops_end: *const c_char,
538 index_base: c_int,
539 result: *mut *mut BoxTuple,
540 ) -> c_int;
541
542 pub fn box_upsert(
543 space_id: u32,
544 index_id: u32,
545 tuple: *const c_char,
546 tuple_end: *const c_char,
547 ops: *const c_char,
548 ops_end: *const c_char,
549 index_base: c_int,
550 result: *mut *mut BoxTuple,
551 ) -> c_int;
552
553 pub fn box_tuple_extract_key(
554 tuple: *const BoxTuple,
555 space_id: u32,
556 index_id: u32,
557 key_size: *mut u32,
558 ) -> *mut c_char;
559 }
560}