use crate::{
errors::ErrorDebug, AppPermissions, Coins, Error, IData, MData, MDataEntries,
MDataPermissionSet, MDataValue, MDataValues, PublicKey, Result, SData, SDataEntries,
SDataEntry, SDataOwner, SDataPermissions, SDataUserPermissions, Signature, Transaction,
};
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeMap, BTreeSet},
convert::TryFrom,
fmt,
};
#[allow(clippy::large_enum_variant, clippy::type_complexity)]
#[derive(Hash, Eq, PartialEq, PartialOrd, Clone, Serialize, Deserialize)]
pub enum Response {
GetIData(Result<IData>),
GetMData(Result<MData>),
GetMDataShell(Result<MData>),
GetMDataVersion(Result<u64>),
ListMDataEntries(Result<MDataEntries>),
ListMDataKeys(Result<BTreeSet<Vec<u8>>>),
ListMDataValues(Result<MDataValues>),
ListMDataUserPermissions(Result<MDataPermissionSet>),
ListMDataPermissions(Result<BTreeMap<PublicKey, MDataPermissionSet>>),
GetMDataValue(Result<MDataValue>),
GetSData(Result<SData>),
GetSDataOwner(Result<SDataOwner>),
GetSDataRange(Result<SDataEntries>),
GetSDataLastEntry(Result<(u64, SDataEntry)>),
GetSDataPermissions(Result<SDataPermissions>),
GetSDataUserPermissions(Result<SDataUserPermissions>),
GetBalance(Result<Coins>),
Transaction(Result<Transaction>),
GetLoginPacket(Result<(Vec<u8>, Signature)>),
ListAuthKeysAndVersion(Result<(BTreeMap<PublicKey, AppPermissions>, u64)>),
Mutation(Result<()>),
}
#[derive(Debug, PartialEq)]
pub enum TryFromError {
WrongType,
Response(Error),
}
macro_rules! try_from {
($ok_type:ty, $($variant:ident),*) => {
impl TryFrom<Response> for $ok_type {
type Error = TryFromError;
fn try_from(response: Response) -> std::result::Result<Self, Self::Error> {
match response {
$(
Response::$variant(Ok(data)) => Ok(data),
Response::$variant(Err(error)) => Err(TryFromError::Response(error)),
)*
_ => Err(TryFromError::WrongType),
}
}
}
};
}
try_from!(IData, GetIData);
try_from!(MData, GetMData, GetMDataShell);
try_from!(u64, GetMDataVersion);
try_from!(MDataEntries, ListMDataEntries);
try_from!(BTreeSet<Vec<u8>>, ListMDataKeys);
try_from!(MDataValues, ListMDataValues);
try_from!(MDataPermissionSet, ListMDataUserPermissions);
try_from!(BTreeMap<PublicKey, MDataPermissionSet>, ListMDataPermissions);
try_from!(MDataValue, GetMDataValue);
try_from!(SData, GetSData);
try_from!(SDataOwner, GetSDataOwner);
try_from!(SDataEntries, GetSDataRange);
try_from!((u64, SDataEntry), GetSDataLastEntry);
try_from!(SDataPermissions, GetSDataPermissions);
try_from!(SDataUserPermissions, GetSDataUserPermissions);
try_from!(Coins, GetBalance);
try_from!(Transaction, Transaction);
try_from!(
(BTreeMap<PublicKey, AppPermissions>, u64),
ListAuthKeysAndVersion
);
try_from!((Vec<u8>, Signature), GetLoginPacket);
try_from!((), Mutation);
impl fmt::Debug for Response {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Response::*;
match self {
GetIData(res) => write!(f, "Response::GetIData({:?})", ErrorDebug(res)),
GetMData(res) => write!(f, "Response::GetMData({:?})", ErrorDebug(res)),
GetMDataShell(res) => write!(f, "Response::GetMDataShell({:?})", ErrorDebug(res)),
GetMDataVersion(res) => write!(f, "Response::GetMDataVersion({:?})", ErrorDebug(res)),
ListMDataEntries(res) => write!(f, "Response::ListMDataEntries({:?})", ErrorDebug(res)),
ListMDataKeys(res) => write!(f, "Response::ListMDataKeys({:?})", ErrorDebug(res)),
ListMDataValues(res) => write!(f, "Response::ListMDataValues({:?})", ErrorDebug(res)),
ListMDataPermissions(res) => {
write!(f, "Response::ListMDataPermissions({:?})", ErrorDebug(res))
}
ListMDataUserPermissions(res) => write!(
f,
"Response::ListMDataUserPermissions({:?})",
ErrorDebug(res)
),
GetMDataValue(res) => write!(f, "Response::GetMDataValue({:?})", ErrorDebug(res)),
GetSData(res) => write!(f, "Response::GetSData({:?})", ErrorDebug(res)),
GetSDataRange(res) => write!(f, "Response::GetSDataRange({:?})", ErrorDebug(res)),
GetSDataLastEntry(res) => {
write!(f, "Response::GetSDataLastEntry({:?})", ErrorDebug(res))
}
GetSDataPermissions(res) => {
write!(f, "Response::GetSDataPermissions({:?})", ErrorDebug(res))
}
GetSDataUserPermissions(res) => write!(
f,
"Response::GetSDataUserPermissions({:?})",
ErrorDebug(res)
),
GetSDataOwner(res) => write!(f, "Response::GetSDataOwner({:?})", ErrorDebug(res)),
GetBalance(res) => write!(f, "Response::GetBalance({:?})", ErrorDebug(res)),
Transaction(res) => write!(f, "Response::Transaction({:?})", ErrorDebug(res)),
GetLoginPacket(res) => write!(f, "Response::GetLoginPacket({:?})", ErrorDebug(res)),
ListAuthKeysAndVersion(res) => {
write!(f, "Response::ListAuthKeysAndVersion({:?})", ErrorDebug(res))
}
Mutation(res) => write!(f, "Response::Mutation({:?})", ErrorDebug(res)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{PubImmutableData, UnseqMutableData};
use std::convert::{TryFrom, TryInto};
use unwrap::{unwrap, unwrap_err};
#[test]
fn debug_format() {
let response = Response::Mutation(Ok(()));
assert_eq!(format!("{:?}", response), "Response::Mutation(Success)");
use crate::Error;
let errored_response = Response::GetSData(Err(Error::AccessDenied));
assert_eq!(
format!("{:?}", errored_response),
"Response::GetSData(AccessDenied)"
);
}
#[test]
fn try_from() {
use Response::*;
let i_data = IData::Pub(PubImmutableData::new(vec![1, 3, 1, 4]));
let e = Error::AccessDenied;
assert_eq!(i_data, unwrap!(GetIData(Ok(i_data.clone())).try_into()));
assert_eq!(
TryFromError::Response(e.clone()),
unwrap_err!(IData::try_from(GetIData(Err(e.clone()))))
);
assert_eq!(
TryFromError::WrongType,
unwrap_err!(IData::try_from(Mutation(Ok(()))))
);
let mut data = BTreeMap::new();
let _ = data.insert(vec![1], vec![10]);
let owners = PublicKey::Bls(threshold_crypto::SecretKey::random().public_key());
let m_data = MData::Unseq(UnseqMutableData::new_with_data(
*i_data.name(),
1,
data,
BTreeMap::new(),
owners,
));
assert_eq!(m_data, unwrap!(GetMData(Ok(m_data.clone())).try_into()));
assert_eq!(
TryFromError::Response(e.clone()),
unwrap_err!(MData::try_from(GetMData(Err(e))))
);
assert_eq!(
TryFromError::WrongType,
unwrap_err!(MData::try_from(Mutation(Ok(()))))
);
}
}