use crate::adb::operation; use bytes::{Buf, BufMut}; use commonware_codec::{Codec, EncodeSize, Error as CodecError, Read, ReadExt, Write}; use commonware_utils::hex; use core::fmt::Display; /// Operations for keyless stores. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub enum Operation { /// Wraps the value appended to the database by this operation. Append(V), /// Indicates the database has been committed. Commit(Option), } impl Operation { /// Returns the value (if any) wrapped by this operation. pub fn into_value(self) -> Option { match self { Self::Append(value) => Some(value), Self::Commit(value) => value, } } } impl EncodeSize for Operation { fn encode_size(&self) -> usize { 1 + match self { Self::Append(v) => v.encode_size(), Self::Commit(v) => v.encode_size(), } } } impl Write for Operation { fn write(&self, buf: &mut impl BufMut) { match &self { Self::Append(value) => { operation::APPEND_CONTEXT.write(buf); value.write(buf); } Self::Commit(metadata) => { operation::COMMIT_CONTEXT.write(buf); metadata.write(buf); } } } } impl Read for Operation { type Cfg = ::Cfg; fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result { match u8::read(buf)? { operation::APPEND_CONTEXT => Ok(Self::Append(V::read_cfg(buf, cfg)?)), operation::COMMIT_CONTEXT => Ok(Self::Commit(Option::::read_cfg(buf, cfg)?)), e => Err(CodecError::InvalidEnum(e)), } } } impl Display for Operation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Append(value) => write!(f, "[append value:{}]", hex(&value.encode())), Self::Commit(value) => { if let Some(value) = value { write!(f, "[commit {}]", hex(&value.encode())) } else { write!(f, "[commit]") } } } } }