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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! Named arguments for the command flags the store takes: write
//! conditions, list ends and positions, and score comparisons.
/// When a write may happen, judged by whether its target already exists:
/// `SET`'s and `ZADD`'s `NX` / `XX`. One value instead of two flags, so
/// asking for both is not expressible.
///
/// ```
/// use kevy_store::{SetCondition, Store};
/// let mut s = Store::new();
/// assert!(!s.set(b"k", b"1".to_vec(), None, SetCondition::IfPresent));
/// assert!(s.set(b"k", b"1".to_vec(), None, SetCondition::IfAbsent));
/// assert!(!s.set(b"k", b"2".to_vec(), None, SetCondition::IfAbsent));
/// assert!(s.set(b"k", b"2".to_vec(), None, SetCondition::Always));
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum SetCondition {
/// Write whether or not the target exists.
///
/// ```
/// use kevy_store::{SetCondition, Store};
/// let mut s = Store::new();
/// assert!(s.set(b"k", b"1".to_vec(), None, SetCondition::Always));
/// assert!(s.set(b"k", b"2".to_vec(), None, SetCondition::Always));
/// assert_eq!(s.get(b"k")?.as_deref(), Some(&b"2"[..]));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
#[default]
Always,
/// `NX`: write only when the target does not exist.
///
/// ```
/// use kevy_store::{SetCondition, Store};
/// let mut s = Store::new();
/// assert!(s.set(b"k", b"1".to_vec(), None, SetCondition::IfAbsent));
/// assert!(!s.set(b"k", b"2".to_vec(), None, SetCondition::IfAbsent));
/// assert_eq!(s.get(b"k")?.as_deref(), Some(&b"1"[..]));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
IfAbsent,
/// `XX`: write only when the target already exists.
///
/// ```
/// use kevy_store::{SetCondition, Store};
/// let mut s = Store::new();
/// assert!(!s.set(b"k", b"1".to_vec(), None, SetCondition::IfPresent));
/// assert_eq!(s.get(b"k")?, None);
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
IfPresent,
}
/// One end of a list: `LEFT` (the head, index 0) or `RIGHT` (the tail).
///
/// ```
/// use kevy_store::{ListEnd, Store};
/// let mut s = Store::new();
/// s.rpush(b"src", &[b"a".as_slice(), b"b".as_slice()]).unwrap();
/// let moved = s.lmove(b"src", b"dst", ListEnd::Right, ListEnd::Left).unwrap();
/// assert_eq!(moved.as_deref(), Some(&b"b"[..]));
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ListEnd {
/// The head: `LPUSH` / `LPOP` side.
///
/// ```
/// use kevy_store::{ListEnd, Store};
/// let mut s = Store::new();
/// s.rpush(b"src", &[b"a".as_slice(), b"b".as_slice()])?;
/// let moved = s.lmove(b"src", b"dst", ListEnd::Left, ListEnd::Left)?;
/// assert_eq!(moved.as_deref(), Some(&b"a"[..]));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
Left,
/// The tail: `RPUSH` / `RPOP` side.
///
/// ```
/// use kevy_store::{ListEnd, Store};
/// let mut s = Store::new();
/// s.rpush(b"src", &[b"a".as_slice(), b"b".as_slice()])?;
/// s.lmove(b"src", b"dst", ListEnd::Right, ListEnd::Right)?;
/// s.lmove(b"src", b"dst", ListEnd::Right, ListEnd::Right)?;
/// assert_eq!(s.lrange(b"dst", 0, -1)?, [b"b".to_vec(), b"a".to_vec()]);
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
Right,
}
/// Where `LINSERT` places the new element relative to its pivot.
///
/// ```
/// use kevy_store::{InsertPosition, Store};
/// let mut s = Store::new();
/// s.rpush(b"l", &[b"a".as_slice(), b"c".as_slice()]).unwrap();
/// assert_eq!(s.linsert(b"l", InsertPosition::Before, b"c", b"b").unwrap(), 3);
/// assert_eq!(s.lrange(b"l", 0, -1).unwrap(), [b"a".to_vec(), b"b".to_vec(), b"c".to_vec()]);
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum InsertPosition {
/// Immediately before the pivot.
///
/// ```
/// use kevy_store::{InsertPosition, Store};
/// let mut s = Store::new();
/// s.rpush(b"l", &[b"b".as_slice()])?;
/// s.linsert(b"l", InsertPosition::Before, b"b", b"a")?;
/// assert_eq!(s.lrange(b"l", 0, -1)?, [b"a".to_vec(), b"b".to_vec()]);
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
Before,
/// Immediately after the pivot.
///
/// ```
/// use kevy_store::{InsertPosition, Store};
/// let mut s = Store::new();
/// s.rpush(b"l", &[b"a".as_slice()])?;
/// s.linsert(b"l", InsertPosition::After, b"a", b"b")?;
/// assert_eq!(s.lrange(b"l", 0, -1)?, [b"a".to_vec(), b"b".to_vec()]);
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
After,
}
/// Which score change a conditional `ZADD` accepts for an existing
/// member: `GT` / `LT`, or any. New members are not judged by it.
///
/// ```
/// use kevy_store::{ScoreCompare, SetCondition, ZaddFlags};
/// let gt = ZaddFlags::new(SetCondition::Always, ScoreCompare::Greater).unwrap();
/// assert_eq!(gt.compare(), ScoreCompare::Greater);
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ScoreCompare {
/// Any new score replaces the old one.
///
/// ```
/// use kevy_store::{ScoreCompare, SetCondition, Store, ZaddFlags};
/// let mut s = Store::new();
/// let any = ZaddFlags::new(SetCondition::Always, ScoreCompare::Any).unwrap();
/// s.zadd(b"z", &[(5.0, b"m".as_slice())])?;
/// s.zadd_flags(b"z", &[(1.0, b"m".as_slice())], any)?;
/// assert_eq!(s.zscore(b"z", b"m")?, Some(1.0));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
#[default]
Any,
/// `GT`: only a greater score replaces the old one.
///
/// ```
/// use kevy_store::{ScoreCompare, SetCondition, Store, ZaddFlags};
/// let mut s = Store::new();
/// let gt = ZaddFlags::new(SetCondition::Always, ScoreCompare::Greater).unwrap();
/// s.zadd(b"z", &[(5.0, b"m".as_slice())])?;
/// s.zadd_flags(b"z", &[(1.0, b"m".as_slice())], gt)?;
/// assert_eq!(s.zscore(b"z", b"m")?, Some(5.0));
/// s.zadd_flags(b"z", &[(9.0, b"m".as_slice())], gt)?;
/// assert_eq!(s.zscore(b"z", b"m")?, Some(9.0));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
Greater,
/// `LT`: only a lesser score replaces the old one.
///
/// ```
/// use kevy_store::{ScoreCompare, SetCondition, Store, ZaddFlags};
/// let mut s = Store::new();
/// let lt = ZaddFlags::new(SetCondition::Always, ScoreCompare::Less).unwrap();
/// s.zadd(b"z", &[(5.0, b"m".as_slice())])?;
/// s.zadd_flags(b"z", &[(9.0, b"m".as_slice())], lt)?;
/// assert_eq!(s.zscore(b"z", b"m")?, Some(5.0));
/// # Ok::<(), kevy_store::StoreError>(())
/// ```
Less,
}