macro_rules! impl_try_from_object {
($ty:ident, $is_fn:ident $(,)?) => {
#[cfg(feature = "serde")]
#[doc = concat!(
"Decode a [`",
stringify!($ty),
"`] from an on-chain object, validating that the object's Move type tag matches."
)]
impl TryFrom<&::iota_types::Object> for $ty {
type Error = $crate::FromObjectError;
fn try_from(object: &::iota_types::Object) -> Result<Self, Self::Error> {
let move_struct = object
.as_opt_struct()
.ok_or($crate::FromObjectError::NotAMoveStruct)?;
if !move_struct.object_type().$is_fn() {
return Err($crate::FromObjectError::WrongType);
}
::bcs::from_bytes(move_struct.contents()).map_err($crate::FromObjectError::Bcs)
}
}
};
($ty:ident $(,)?) => {
::paste::paste! {
impl_try_from_object!($ty, [< is_ $ty:snake >]);
}
};
}
macro_rules! impl_try_from_object_generic {
($ty:ident<$param:ident>, $is_fn:ident $(,)?) => {
#[cfg(feature = "serde")]
impl<$param> $ty<$param>
where
$param: ::serde::de::DeserializeOwned,
{
#[doc = concat!(
"Decode a [`",
stringify!($ty),
"`] from an on-chain object, validating its Move type tag and that its type parameter equals `type_param`.\n\nEscape hatch for type parameters only known at runtime; nothing ties `type_param` to `",
stringify!($param),
"`. Prefer the `TryFrom` impl when the type parameter is known at compile time."
)]
pub fn try_from_object_with_type(
object: &::iota_types::Object,
type_param: &::iota_types::TypeTag,
) -> Result<Self, $crate::FromObjectError> {
let move_struct = object
.as_opt_struct()
.ok_or($crate::FromObjectError::NotAMoveStruct)?;
let tag = move_struct.struct_tag();
if !tag.$is_fn() || tag.type_params() != ::core::slice::from_ref(type_param) {
return Err($crate::FromObjectError::WrongType);
}
::bcs::from_bytes(move_struct.contents()).map_err($crate::FromObjectError::Bcs)
}
}
#[cfg(feature = "serde")]
#[doc = concat!(
"Decode a [`",
stringify!($ty),
"`] from an on-chain object, validating its full Move type tag including the type parameter."
)]
impl<$param> TryFrom<&::iota_types::Object> for $ty<$param>
where
$param: ::serde::de::DeserializeOwned + $crate::MoveType,
{
type Error = $crate::FromObjectError;
fn try_from(object: &::iota_types::Object) -> Result<Self, Self::Error> {
Self::try_from_object_with_type(object, &<$param as $crate::MoveType>::type_tag())
}
}
};
($ty:ident<$param:ident> $(,)?) => {
::paste::paste! {
impl_try_from_object_generic!($ty<$param>, [< is_ $ty:snake >]);
}
};
}