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
//! Box: sequences
use crate::error::{Error, TarantoolError};
use crate::space::{Space, SystemSpace};
use crate::tuple::AsTuple;
/// A sequence is a generator of ordered integer values.
pub struct Sequence {
seq_id: u32,
}
impl Sequence {
/// Find sequence by name.
pub fn find(name: &str) -> Result<Option<Self>, Error> {
#[derive(Serialize, Deserialize)]
struct Row {
seq_id: u32,
}
impl AsTuple for Row {}
let space: Space = SystemSpace::Sequence.into();
let name_idx = space.index("name").unwrap();
Ok(match name_idx.get(&(name,))? {
None => None,
Some(row_tuple) => Some(Sequence {
seq_id: row_tuple.into_struct::<Row>()?.seq_id,
}),
})
}
/// Generate the next value and return it.
///
/// The generation algorithm is simple:
/// - If this is the first time, then return the `start` value.
/// - If the previous value plus the `increment` value is less than the `minimum` value or greater than the
/// `maximum` value, that is "overflow", so either raise an error (if `cycle = false`) or return the `maximum` value
/// (if `cycle = true` and `step < 0`) or return the `minimum` value (if `cycle = true` and `step > 0`).
///
/// If there was no error, then save the returned result, it is now the "previous value".
pub fn next(&mut self) -> Result<i64, Error> {
let mut result: i64 = 0;
if unsafe { ffi::box_sequence_next(self.seq_id, &mut result) } < 0 {
Err(TarantoolError::last().into())
} else {
Ok(result)
}
}
/// Set the "previous value" to `new_value`.
///
/// This function requires a "write" privilege on the sequence.
pub fn set(&mut self, new_value: i64) -> Result<(), Error> {
if unsafe { ffi::box_sequence_set(self.seq_id, new_value) } < 0 {
Err(TarantoolError::last().into())
} else {
Ok(())
}
}
/// Set the sequence back to its original state.
///
/// The effect is that a subsequent [next](#method.next) will return the start value.
/// This function requires a "write" privilege on the sequence.
pub fn reset(&mut self) -> Result<(), Error> {
if unsafe { ffi::box_sequence_reset(self.seq_id) } < 0 {
Err(TarantoolError::last().into())
} else {
Ok(())
}
}
}
mod ffi {
use std::os::raw::c_int;
extern "C" {
pub fn box_sequence_next(seq_id: u32, result: *mut i64) -> c_int;
pub fn box_sequence_set(seq_id: u32, value: i64) -> c_int;
pub fn box_sequence_reset(seq_id: u32) -> c_int;
}
}