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
//! Put operation types.
//!
//! Put operation mode enum.
/// Type of put operation for cursors and databases.
///
/// Specifies how to insert or update records.
///
/// Put operation mode enum.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Put {
/// Insert if the key doesn't exist, else return error.
///
/// For non-duplicate databases, returns an error if the key exists.
/// For duplicate databases, returns an error if the key/data pair exists.
NoOverwrite,
/// Insert or update (default behavior).
///
/// For non-duplicate databases, inserts if the key doesn't exist, or
/// replaces the data if the key exists. For duplicate databases, inserts
/// a new duplicate.
Overwrite,
/// Insert if key doesn't exist, else do nothing.
///
/// Similar to NoOverwrite, but returns success (with no update) if the
/// key already exists, rather than an error. For duplicate databases,
/// returns success if the key/data pair exists.
NoDupData,
/// Update the record at the current cursor position.
///
/// Replaces the data at the current cursor position. The key cannot be
/// changed. Returns an error if the cursor is not positioned.
Current,
}
impl Put {
/// Returns whether this operation allows overwriting existing records.
pub fn allows_overwrite(&self) -> bool {
matches!(self, Put::Overwrite | Put::Current)
}
/// Returns whether this operation returns an error if the record exists.
pub fn errors_if_exists(&self) -> bool {
matches!(self, Put::NoOverwrite)
}
/// Returns whether this operation requires the cursor to be positioned.
pub fn requires_positioned_cursor(&self) -> bool {
matches!(self, Put::Current)
}
/// Returns whether this operation prevents duplicate data.
pub fn prevents_duplicates(&self) -> bool {
matches!(self, Put::NoDupData)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_allows_overwrite() {
assert!(Put::Overwrite.allows_overwrite());
assert!(Put::Current.allows_overwrite());
assert!(!Put::NoOverwrite.allows_overwrite());
assert!(!Put::NoDupData.allows_overwrite());
}
#[test]
fn test_errors_if_exists() {
assert!(Put::NoOverwrite.errors_if_exists());
assert!(!Put::Overwrite.errors_if_exists());
assert!(!Put::NoDupData.errors_if_exists());
assert!(!Put::Current.errors_if_exists());
}
#[test]
fn test_requires_positioned_cursor() {
assert!(Put::Current.requires_positioned_cursor());
assert!(!Put::Overwrite.requires_positioned_cursor());
assert!(!Put::NoOverwrite.requires_positioned_cursor());
assert!(!Put::NoDupData.requires_positioned_cursor());
}
#[test]
fn test_prevents_duplicates() {
assert!(Put::NoDupData.prevents_duplicates());
assert!(!Put::Overwrite.prevents_duplicates());
assert!(!Put::NoOverwrite.prevents_duplicates());
assert!(!Put::Current.prevents_duplicates());
}
#[test]
fn test_equality() {
assert_eq!(Put::NoOverwrite, Put::NoOverwrite);
assert_ne!(Put::NoOverwrite, Put::Overwrite);
}
#[test]
fn test_debug() {
let put = Put::NoDupData;
let debug = format!("{:?}", put);
assert_eq!(debug, "NoDupData");
}
#[test]
fn test_all_variants() {
let variants =
[Put::NoOverwrite, Put::Overwrite, Put::NoDupData, Put::Current];
// Just ensure all variants are created successfully
assert_eq!(variants.len(), 4);
}
}