tarantool_module/
sequence.rs

1//! Box: sequences
2use crate::error::{Error, TarantoolError};
3use crate::space::{Space, SystemSpace};
4use crate::tuple::AsTuple;
5
6/// A sequence is a generator of ordered integer values.
7pub struct Sequence {
8    seq_id: u32,
9}
10
11impl Sequence {
12    /// Find sequence by name.
13    pub fn find(name: &str) -> Result<Option<Self>, Error> {
14        #[derive(Serialize, Deserialize)]
15        struct Row {
16            seq_id: u32,
17        }
18
19        impl AsTuple for Row {}
20
21        let space: Space = SystemSpace::Sequence.into();
22        let name_idx = space.index("name").unwrap();
23
24        Ok(match name_idx.get(&(name,))? {
25            None => None,
26            Some(row_tuple) => Some(Sequence {
27                seq_id: row_tuple.into_struct::<Row>()?.seq_id,
28            }),
29        })
30    }
31
32    /// Generate the next value and return it.
33    ///
34    /// The generation algorithm is simple:
35    /// - If this is the first time, then return the `start` value.
36    /// - If the previous value plus the `increment` value is less than the `minimum` value or greater than the
37    /// `maximum` value, that is "overflow", so either raise an error (if `cycle = false`) or return the `maximum` value
38    /// (if `cycle = true` and `step < 0`) or return the `minimum` value (if `cycle = true` and `step > 0`).
39    ///
40    /// If there was no error, then save the returned result, it is now the "previous value".
41    pub fn next(&mut self) -> Result<i64, Error> {
42        let mut result: i64 = 0;
43        if unsafe { ffi::box_sequence_next(self.seq_id, &mut result) } < 0 {
44            Err(TarantoolError::last().into())
45        } else {
46            Ok(result)
47        }
48    }
49
50    /// Set the "previous value" to `new_value`.
51    ///
52    /// This function requires a "write" privilege on the sequence.
53    pub fn set(&mut self, new_value: i64) -> Result<(), Error> {
54        if unsafe { ffi::box_sequence_set(self.seq_id, new_value) } < 0 {
55            Err(TarantoolError::last().into())
56        } else {
57            Ok(())
58        }
59    }
60
61    /// Set the sequence back to its original state.
62    ///
63    /// The effect is that a subsequent [next](#method.next) will return the start value.
64    /// This function requires a "write" privilege on the sequence.
65    pub fn reset(&mut self) -> Result<(), Error> {
66        if unsafe { ffi::box_sequence_reset(self.seq_id) } < 0 {
67            Err(TarantoolError::last().into())
68        } else {
69            Ok(())
70        }
71    }
72}
73
74mod ffi {
75    use std::os::raw::c_int;
76
77    extern "C" {
78        pub fn box_sequence_next(seq_id: u32, result: *mut i64) -> c_int;
79        pub fn box_sequence_set(seq_id: u32, value: i64) -> c_int;
80        pub fn box_sequence_reset(seq_id: u32) -> c_int;
81    }
82}