commonware_storage/qmdb/immutable/operation/
mod.rs1pub(crate) mod fixed;
10pub(crate) mod variable;
11
12use crate::{
13 merkle::{Family, Location},
14 qmdb::{
15 any::ValueEncoding,
16 operation::{Key, Operation as OperationTrait},
17 },
18};
19use commonware_codec::Encode;
20use commonware_utils::hex;
21use core::fmt::Display;
22
23pub(crate) const SET_CONTEXT: u8 = 0;
25pub(crate) const COMMIT_CONTEXT: u8 = 1;
26
27#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
32pub enum Operation<K: Key, V: ValueEncoding> {
33 Set(K, V::Value),
35
36 Commit(Option<V::Value>),
38}
39
40impl<K: Key, V: ValueEncoding> Operation<K, V> {
41 pub const fn key(&self) -> Option<&K> {
43 match self {
44 Self::Set(key, _) => Some(key),
45 Self::Commit(_) => None,
46 }
47 }
48
49 pub const fn is_commit(&self) -> bool {
51 matches!(self, Self::Commit(_))
52 }
53}
54
55impl<F: Family, K: Key, V: ValueEncoding> OperationTrait<F> for Operation<K, V> {
56 type Key = K;
57
58 fn key(&self) -> Option<&Self::Key> {
59 self.key()
60 }
61
62 fn is_delete(&self) -> bool {
63 false
65 }
66
67 fn is_update(&self) -> bool {
68 matches!(self, Self::Set(_, _))
69 }
70
71 fn has_floor(&self) -> Option<Location<F>> {
72 None
74 }
75}
76
77impl<K: Key, V: ValueEncoding> Display for Operation<K, V>
78where
79 V::Value: Encode,
80{
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 match self {
83 Self::Set(key, value) => {
84 write!(f, "[key:{} value:{}]", hex(key), hex(&value.encode()))
85 }
86 Self::Commit(value) => {
87 if let Some(value) = value {
88 write!(f, "[commit {}]", hex(&value.encode()))
89 } else {
90 write!(f, "[commit]")
91 }
92 }
93 }
94 }
95}
96
97#[cfg(feature = "arbitrary")]
98impl<K: Key, V: ValueEncoding> arbitrary::Arbitrary<'_> for Operation<K, V>
99where
100 K: for<'a> arbitrary::Arbitrary<'a>,
101 V::Value: for<'a> arbitrary::Arbitrary<'a>,
102{
103 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
104 let choice = u.int_in_range(0..=1)?;
105 match choice {
106 0 => {
107 let key = K::arbitrary(u)?;
108 let value = V::Value::arbitrary(u)?;
109 Ok(Self::Set(key, value))
110 }
111 1 => Ok(Self::Commit(Option::<V::Value>::arbitrary(u)?)),
112 _ => unreachable!(),
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::qmdb::any::value::VariableEncoding;
121 use commonware_codec::Encode;
122 use commonware_utils::sequence::U64;
123
124 type VarOp = Operation<U64, VariableEncoding<U64>>;
125
126 #[test]
127 fn test_operation_key() {
128 let key = U64::new(1234);
129 let value = U64::new(56789);
130
131 let set_op = VarOp::Set(key.clone(), value.clone());
132 assert_eq!(&key, set_op.key().unwrap());
133
134 let commit_op = VarOp::Commit(Some(value));
135 assert_eq!(None, commit_op.key());
136
137 let commit_op_none = VarOp::Commit(None);
138 assert_eq!(None, commit_op_none.key());
139 }
140
141 #[test]
142 fn test_operation_is_commit() {
143 let key = U64::new(1234);
144 let value = U64::new(56789);
145
146 let set_op = VarOp::Set(key, value.clone());
147 assert!(!set_op.is_commit());
148
149 let commit_op = VarOp::Commit(Some(value));
150 assert!(commit_op.is_commit());
151
152 let commit_op_none = VarOp::Commit(None);
153 assert!(commit_op_none.is_commit());
154 }
155
156 #[test]
157 fn test_operation_display() {
158 let key = U64::new(1234);
159 let value = U64::new(56789);
160
161 let set_op = VarOp::Set(key.clone(), value.clone());
162 assert_eq!(
163 format!("{set_op}"),
164 format!("[key:{} value:{}]", hex(&key), hex(&value.encode()))
165 );
166
167 let commit_op = VarOp::Commit(Some(value.clone()));
168 assert_eq!(
169 format!("{commit_op}"),
170 format!("[commit {}]", hex(&value.encode()))
171 );
172
173 let commit_op = VarOp::Commit(None);
174 assert_eq!(format!("{commit_op}"), "[commit]");
175 }
176}