casper_erc20_crate/
address.rs

1//! Implementation of an `Address` which refers either an account hash, or a contract hash.
2use alloc::{string::ToString, vec::Vec};
3use casper_contract::contract_api::runtime;
4use casper_types::{
5    account::AccountHash,
6    bytesrepr::{self, FromBytes, ToBytes},
7    ApiError, CLType, CLTyped, ContractPackageHash, Key,
8};
9
10/// An enum representing an [`AccountHash`] or a [`ContractPackageHash`].
11#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy, Debug)]
12pub enum Address {
13    /// Represents an account hash.
14    Account(AccountHash),
15    /// Represents a contract package hash.
16    Contract(ContractPackageHash),
17}
18
19impl Address {
20    /// Returns the inner account hash if `self` is the `Account` variant.
21    pub fn as_account_hash(&self) -> Option<&AccountHash> {
22        if let Self::Account(v) = self {
23            Some(v)
24        } else {
25            None
26        }
27    }
28
29    /// Returns the inner contract hash if `self` is the `Contract` variant.
30    pub fn as_contract_package_hash(&self) -> Option<&ContractPackageHash> {
31        if let Self::Contract(v) = self {
32            Some(v)
33        } else {
34            None
35        }
36    }
37}
38
39impl ToString for Address {
40    fn to_string(&self) -> alloc::string::String {
41        if self.as_account_hash().is_some() {
42            self.as_account_hash().unwrap().to_string()
43        } else if self.as_contract_package_hash().is_some() {
44            self.as_contract_package_hash().unwrap().to_string()
45        } else {
46            runtime::revert(ApiError::ValueNotFound)
47        }
48    }
49}
50
51impl From<ContractPackageHash> for Address {
52    fn from(contract_package_hash: ContractPackageHash) -> Self {
53        Self::Contract(contract_package_hash)
54    }
55}
56
57impl From<AccountHash> for Address {
58    fn from(account_hash: AccountHash) -> Self {
59        Self::Account(account_hash)
60    }
61}
62
63impl From<Key> for Address {
64    fn from(key: Key) -> Self {
65        match key {
66            Key::Account(account_hash) => Address::Account(account_hash),
67            Key::Hash(hash) => Address::Contract(hash.into()),
68            _ => runtime::revert(ApiError::UnexpectedKeyVariant),
69        }
70    }
71}
72
73impl From<Address> for Key {
74    fn from(address: Address) -> Self {
75        match address {
76            Address::Account(account_hash) => Key::Account(account_hash),
77            Address::Contract(contract_package_hash) => Key::Hash(contract_package_hash.value()),
78        }
79    }
80}
81
82impl CLTyped for Address {
83    fn cl_type() -> casper_types::CLType {
84        CLType::Key
85    }
86}
87
88impl ToBytes for Address {
89    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
90        Key::from(*self).to_bytes()
91    }
92
93    fn serialized_length(&self) -> usize {
94        Key::from(*self).serialized_length()
95    }
96}
97
98impl FromBytes for Address {
99    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
100        let (key, remainder) = Key::from_bytes(bytes)?;
101
102        let address = match key {
103            Key::Account(account_hash) => Address::Account(account_hash),
104            Key::Hash(raw_contract_package_hash) => {
105                let contract_package_hash = ContractPackageHash::new(raw_contract_package_hash);
106                Address::Contract(contract_package_hash)
107            }
108            _ => return Err(bytesrepr::Error::Formatting),
109        };
110
111        Ok((address, remainder))
112    }
113}