macro_rules! versioned_msgpack_blob {
(
blob: $Blob:ty,
item: $Item:ty,
field: $field:ident,
error: $Err:ty,
codec_err: $codec:ident,
version: $ver:expr $(,)?
) => {
impl $Blob {
pub const FORMAT_VERSION: u8 = $ver;
pub fn new($field: ::std::vec::Vec<$Item>) -> Self {
Self {
format_version: Self::FORMAT_VERSION,
$field,
}
}
pub fn encode(&self) -> ::core::result::Result<::std::vec::Vec<u8>, $Err> {
rmp_serde::to_vec(self).map_err(|err| <$Err>::$codec(err.to_string()))
}
pub fn decode(bytes: &[u8]) -> ::core::result::Result<Self, $Err> {
let blob: Self =
rmp_serde::from_slice(bytes).map_err(|err| <$Err>::$codec(err.to_string()))?;
blob.validate()?;
Ok(blob)
}
pub fn validate(&self) -> ::core::result::Result<(), $Err> {
if self.format_version != Self::FORMAT_VERSION {
return Err(<$Err>::UnsupportedVersion(self.format_version));
}
for item in &self.$field {
item.validate()?;
}
Ok(())
}
}
};
}