commonware_storage/qmdb/
operation.rs1use crate::merkle::{Family, Location};
4use commonware_codec::{
5 CodecShared, EncodeSize, Error as CodecError, FixedSize, Read, ReadExt as _, Write,
6 util::ensure_zeros,
7};
8use commonware_runtime::{Buf, BufMut};
9use core::{fmt::Debug, hash::Hash, ops::Deref};
10
11pub trait Key:
14 CodecShared + Clone + 'static + Eq + Ord + Hash + AsRef<[u8]> + Deref<Target = [u8]> + Debug
15{
16}
17
18impl<T> Key for T where
19 T: CodecShared + Clone + 'static + Eq + Ord + Hash + AsRef<[u8]> + Deref<Target = [u8]> + Debug
20{
21}
22
23pub trait Floored<F: Family> {
25 fn has_floor(&self) -> Option<Location<F>>;
28}
29
30pub trait Operation<F: Family>: Floored<F> {
32 type Key: Key;
34
35 fn key(&self) -> Option<&Self::Key>;
37
38 fn into_key(self) -> Option<Self::Key>;
40
41 fn is_update(&self) -> bool;
43
44 fn is_delete(&self) -> bool;
46}
47
48pub trait Committable {
50 fn is_commit(&self) -> bool;
52}
53
54pub(crate) const fn commit_fixed_operation_size<V: FixedSize>() -> usize {
56 1 + 1 + V::SIZE + u64::SIZE
57}
58
59pub(crate) fn write_commit_fixed<F: Family, V: Write + FixedSize>(
61 metadata: &Option<V>,
62 floor: Location<F>,
63 buf: &mut impl BufMut,
64) {
65 if let Some(value) = metadata {
66 true.write(buf);
67 value.write(buf);
68 } else {
69 buf.put_bytes(0, 1 + V::SIZE);
70 }
71 buf.put_slice(&floor.as_u64().to_be_bytes());
72}
73
74pub(crate) fn read_commit_fixed<F: Family, V: Read<Cfg = ()> + FixedSize>(
76 buf: &mut impl Buf,
77) -> Result<(Option<V>, Location<F>), CodecError> {
78 let metadata = if bool::read(buf)? {
79 Some(V::read(buf)?)
80 } else {
81 ensure_zeros(buf, V::SIZE)?;
82 None
83 };
84 let floor = Location::new(u64::read(buf)?);
85 if !floor.is_valid() {
86 return Err(CodecError::Invalid(
87 "storage::qmdb::operation::commit",
88 "commit floor location overflow",
89 ));
90 }
91 Ok((metadata, floor))
92}
93
94pub(crate) fn commit_variable_payload_size<F: Family, V: EncodeSize>(
96 metadata: &Option<V>,
97 floor: Location<F>,
98) -> usize {
99 metadata.encode_size() + floor.encode_size()
100}
101
102pub(crate) fn write_commit_variable<F: Family, V: Write>(
104 metadata: &Option<V>,
105 floor: Location<F>,
106 buf: &mut impl BufMut,
107) {
108 metadata.write(buf);
109 floor.write(buf);
110}
111
112pub(crate) fn read_commit_variable<F: Family, V: Read>(
114 buf: &mut impl Buf,
115 value_cfg: &V::Cfg,
116) -> Result<(Option<V>, Location<F>), CodecError> {
117 let metadata = Option::<V>::read_cfg(buf, value_cfg)?;
118 let floor = Location::read(buf)?;
119 Ok((metadata, floor))
120}