Skip to main content

commonware_storage/qmdb/any/operation/
variable.rs

1use crate::{
2    merkle::{Family, Location},
3    qmdb::{
4        any::{
5            operation::{
6                update, Operation, OperationCodec, Update, COMMIT_CONTEXT, DELETE_CONTEXT,
7                UPDATE_CONTEXT,
8            },
9            value::VariableEncoding,
10            VariableValue,
11        },
12        operation::Key,
13    },
14};
15use commonware_codec::{varint::UInt, EncodeSize, Error as CodecError, Read, ReadExt as _, Write};
16use commonware_runtime::{Buf, BufMut};
17
18impl<F, V, S> OperationCodec<F, S> for VariableEncoding<V>
19where
20    F: Family,
21    S::Key: Write + Read,
22    V: VariableValue,
23    S: Update<Value = V, ValueEncoding = Self>
24        + Write
25        + Read<Cfg = (<S::Key as Read>::Cfg, <V as Read>::Cfg)>,
26{
27    type ReadCfg = (<S::Key as Read>::Cfg, <V as Read>::Cfg);
28
29    fn write_operation(op: &Operation<F, S>, buf: &mut impl BufMut) {
30        match op {
31            Operation::Delete(k) => {
32                DELETE_CONTEXT.write(buf);
33                k.write(buf);
34            }
35            Operation::Update(p) => {
36                UPDATE_CONTEXT.write(buf);
37                p.write(buf);
38            }
39            Operation::CommitFloor(metadata, floor_loc) => {
40                COMMIT_CONTEXT.write(buf);
41                metadata.write(buf);
42                UInt(**floor_loc).write(buf);
43            }
44        }
45    }
46
47    fn read_operation(
48        buf: &mut impl Buf,
49        cfg: &Self::ReadCfg,
50    ) -> Result<Operation<F, S>, CodecError> {
51        match u8::read(buf)? {
52            DELETE_CONTEXT => {
53                let key = S::Key::read_cfg(buf, &cfg.0)?;
54                Ok(Operation::Delete(key))
55            }
56            UPDATE_CONTEXT => {
57                let payload = S::read_cfg(buf, cfg)?;
58                Ok(Operation::Update(payload))
59            }
60            COMMIT_CONTEXT => {
61                let metadata = Option::<V>::read_cfg(buf, &cfg.1)?;
62                let floor_loc = Location::read(buf)?;
63                Ok(Operation::CommitFloor(metadata, floor_loc))
64            }
65            e => Err(CodecError::InvalidEnum(e)),
66        }
67    }
68}
69
70// EncodeSize for ordered variable operations.
71impl<F, K, V> EncodeSize for Operation<F, update::Ordered<K, VariableEncoding<V>>>
72where
73    F: Family,
74    K: Key + EncodeSize,
75    V: VariableValue,
76    update::Ordered<K, VariableEncoding<V>>: EncodeSize,
77{
78    fn encode_size(&self) -> usize {
79        1 + match self {
80            Self::Delete(k) => k.encode_size(),
81            Self::Update(p) => p.encode_size(),
82            Self::CommitFloor(v, floor) => v.encode_size() + UInt(**floor).encode_size(),
83        }
84    }
85}
86
87// EncodeSize for unordered variable operations.
88impl<F, K, V> EncodeSize for Operation<F, update::Unordered<K, VariableEncoding<V>>>
89where
90    F: Family,
91    K: Key + EncodeSize,
92    V: VariableValue,
93    update::Unordered<K, VariableEncoding<V>>: EncodeSize,
94{
95    fn encode_size(&self) -> usize {
96        1 + match self {
97            Self::Delete(k) => k.encode_size(),
98            Self::Update(p) => p.encode_size(),
99            Self::CommitFloor(v, floor) => v.encode_size() + UInt(**floor).encode_size(),
100        }
101    }
102}