Skip to main content

sift_query_core/cursor/
value.rs

1use super::invalid_cursor;
2use crate::{ParamError, RowValue, ScalarValue};
3
4#[derive(Debug, Clone, PartialEq)]
5pub enum CursorValue {
6    Null,
7    Scalar(ScalarValue),
8}
9
10pub trait IntoCursorValue {
11    fn to_cursor_value(&self) -> CursorValue;
12}
13
14macro_rules! impl_cursor_value {
15    ($type:ty, $variant:ident) => {
16        impl IntoCursorValue for $type {
17            fn to_cursor_value(&self) -> CursorValue {
18                CursorValue::Scalar(ScalarValue::$variant(self.clone()))
19            }
20        }
21    };
22}
23
24impl_cursor_value!(bool, Bool);
25impl_cursor_value!(i32, I32);
26impl_cursor_value!(i64, I64);
27impl_cursor_value!(f32, F32);
28impl_cursor_value!(f64, F64);
29impl_cursor_value!(String, Text);
30impl_cursor_value!(Vec<u8>, Bytes);
31#[cfg(feature = "decimal")]
32impl_cursor_value!(rust_decimal::Decimal, Decimal);
33#[cfg(feature = "chrono")]
34impl_cursor_value!(chrono::NaiveDate, Date);
35#[cfg(feature = "chrono")]
36impl_cursor_value!(chrono::NaiveTime, Time);
37#[cfg(feature = "chrono")]
38impl_cursor_value!(chrono::NaiveDateTime, DateTime);
39#[cfg(feature = "chrono")]
40impl_cursor_value!(chrono::DateTime<chrono::Utc>, Timestamp);
41#[cfg(feature = "uuid")]
42impl_cursor_value!(uuid::Uuid, Uuid);
43
44impl<T: IntoCursorValue> IntoCursorValue for Option<T> {
45    fn to_cursor_value(&self) -> CursorValue {
46        self.as_ref()
47            .map_or(CursorValue::Null, IntoCursorValue::to_cursor_value)
48    }
49}
50
51#[derive(Debug, Clone, PartialEq)]
52pub struct Cursor {
53    pub(super) values: Vec<CursorValue>,
54}
55
56impl Cursor {
57    #[must_use]
58    pub fn values(&self) -> &[CursorValue] {
59        &self.values
60    }
61}
62
63impl CursorValue {
64    pub fn from_row_value(value: &RowValue) -> Result<Self, ParamError> {
65        Ok(match value {
66            RowValue::List(_) => return Err(invalid_cursor("lists cannot be cursor keys")),
67            #[cfg(feature = "postgres-types")]
68            RowValue::ArrayI64(_)
69            | RowValue::ArrayText(_)
70            | RowValue::Int8Range(_)
71            | RowValue::Network(_) => {
72                return Err(invalid_cursor("native types cannot be cursor keys"));
73            }
74            RowValue::Null => Self::Null,
75            RowValue::Bool(value) => Self::Scalar(ScalarValue::Bool(*value)),
76            RowValue::I32(value) => Self::Scalar(ScalarValue::I32(*value)),
77            RowValue::I64(value) => Self::Scalar(ScalarValue::I64(*value)),
78            RowValue::F32(value) => Self::Scalar(ScalarValue::F32(*value)),
79            RowValue::F64(value) => Self::Scalar(ScalarValue::F64(*value)),
80            #[cfg(feature = "decimal")]
81            RowValue::Decimal(value) => Self::Scalar(ScalarValue::Decimal(*value)),
82            RowValue::Text(value) => Self::Scalar(ScalarValue::Text(value.clone())),
83            RowValue::Bytes(value) => Self::Scalar(ScalarValue::Bytes(value.clone())),
84            #[cfg(feature = "chrono")]
85            RowValue::Date(value) => Self::Scalar(ScalarValue::Date(*value)),
86            #[cfg(feature = "chrono")]
87            RowValue::Time(value) => Self::Scalar(ScalarValue::Time(*value)),
88            #[cfg(feature = "chrono")]
89            RowValue::DateTime(value) => Self::Scalar(ScalarValue::DateTime(*value)),
90            #[cfg(feature = "chrono")]
91            RowValue::Timestamp(value) => Self::Scalar(ScalarValue::Timestamp(*value)),
92            #[cfg(feature = "uuid")]
93            RowValue::Uuid(value) => Self::Scalar(ScalarValue::Uuid(*value)),
94            #[cfg(feature = "json")]
95            RowValue::Json(_) => return Err(invalid_cursor("JSON cannot be a cursor key")),
96        })
97    }
98}