use std::string::{String, ToString};
use std::vec::Vec;
use miden_client::store::StoreError;
use miden_client::utils::DeserializationError;
use miden_objects::ConversionError;
mod input_note;
mod output_note;
mod protocol;
mod transaction;
pub use output_note::{decode_output_note_state, encode_output_note_state};
pub use protocol::{decode_mmr_peaks, encode_mmr_peaks};
#[rustfmt::skip]
#[allow(
clippy::doc_markdown,
clippy::large_enum_variant,
clippy::struct_field_names,
clippy::trivially_copy_pass_by_ref,
missing_docs
)]
mod generated {
include!(concat!(env!("OUT_DIR"), "/miden.client.store.rs"));
}
pub use generated::*;
pub trait ProtobufValue: Sized {
type Message: prost::Message + Default;
fn to_proto(&self) -> Self::Message;
fn from_proto(message: Self::Message) -> Result<Self, ProtoDecodeError>;
}
pub fn encode<T: ProtobufValue>(value: &T) -> Vec<u8> {
prost::Message::encode_to_vec(&value.to_proto())
}
pub fn decode<T: ProtobufValue>(bytes: &[u8]) -> Result<T, ProtoDecodeError> {
let message = <T::Message as prost::Message>::decode(bytes)?;
T::from_proto(message)
}
#[derive(Debug, thiserror::Error)]
pub enum ProtoDecodeError {
#[error("invalid protobuf message: {0}")]
Wire(#[from] prost::DecodeError),
#[error(transparent)]
UnknownEnumValue(#[from] prost::UnknownEnumValue),
#[error("{message} has no {field}")]
MissingField {
message: &'static str,
field: &'static str,
},
#[error("invalid protocol value: {0}")]
Conversion(#[from] ConversionError),
#[error("invalid value: {0}")]
InvalidValue(String),
}
impl From<ProtoDecodeError> for StoreError {
fn from(err: ProtoDecodeError) -> Self {
StoreError::DataDeserializationError(DeserializationError::InvalidValue(err.to_string()))
}
}
pub(crate) fn required<T>(
field: Option<T>,
message: &'static str,
name: &'static str,
) -> Result<T, ProtoDecodeError> {
field.ok_or(ProtoDecodeError::MissingField { message, field: name })
}
#[cfg(test)]
mod tests {
use miden_client::note::BlockNumber;
use miden_client::transaction::TransactionStatus;
use super::*;
#[test]
fn decoding_skips_unknown_fields() {
let status = TransactionStatus::Committed {
block_number: BlockNumber::from(7u32),
commit_timestamp: 42,
};
let mut bytes = encode(&status);
bytes.extend_from_slice(&[15 << 3, 1]);
assert_eq!(decode::<TransactionStatus>(&bytes).unwrap(), status);
}
}