use super::errors::{DecodingError, EncodingError};
use mazze_types::address_util::{self, AddressUtil};
use std::{fmt, string::ToString};
pub const CHARSET_SIZE: usize = 32;
pub const RESERVED_BITS_MASK: u8 = 0xf8;
pub const SIZE_MASK: u8 = 0x07;
pub const SIZE_160: u8 = 0x00;
pub const SIZE_192: u8 = 0x01;
pub const SIZE_224: u8 = 0x02;
pub const SIZE_256: u8 = 0x03;
pub const SIZE_320: u8 = 0x04;
pub const SIZE_384: u8 = 0x05;
pub const SIZE_448: u8 = 0x06;
pub const SIZE_512: u8 = 0x07;
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum Network {
Main,
Test,
Id(u64),
}
const MAINNET_PREFIX: &str = "mazze";
const TESTNET_PREFIX: &str = "mazzetest";
const NETWORK_ID_PREFIX: &str = "net";
const RESERVED_NETWORK_IDS: [u64; 2] = [1, 1029];
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum AddressType {
Builtin,
Contract,
Null,
User,
Unknown,
}
impl fmt::Display for Network {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.to_prefix() {
Err(EncodingError::InvalidNetworkId(network_id)) => {
write!(f, "invalid network prefix net{}", network_id)
}
Err(_) => unreachable!(),
Ok(prefix) => write!(f, "{}", prefix),
}
}
}
impl Network {
pub fn to_prefix(&self) -> Result<String, EncodingError> {
match self {
Network::Main => Ok(MAINNET_PREFIX.into()),
Network::Test => Ok(TESTNET_PREFIX.into()),
Network::Id(network_id) => {
if RESERVED_NETWORK_IDS.contains(network_id) {
Err(EncodingError::InvalidNetworkId(*network_id))
} else {
Ok(format!("net{}", network_id))
}
}
}
}
pub fn from_prefix(prefix: &str) -> Result<Self, DecodingError> {
match prefix {
MAINNET_PREFIX => Ok(Network::Main),
TESTNET_PREFIX => Ok(Network::Test),
_ => {
let maybe_network_id = if !prefix.starts_with(NETWORK_ID_PREFIX)
{
None
} else {
match prefix[NETWORK_ID_PREFIX.len()..].parse::<u64>() {
Err(_) => None,
Ok(network_id) => {
if RESERVED_NETWORK_IDS.contains(&network_id) {
None
} else {
Some(network_id)
}
}
}
};
match maybe_network_id {
None => {
Err(DecodingError::InvalidPrefix(prefix.to_string()))
}
Some(network_id) => Ok(Network::Id(network_id)),
}
}
}
}
}
impl AddressType {
const BUILTIN: &'static str = "builtin";
const CONTRACT: &'static str = "contract";
const NULL: &'static str = "null";
const UNKNOWN: &'static str = "unknown";
const USER: &'static str = "user";
pub fn parse(text: &str) -> Result<Self, DecodingError> {
if text == Self::BUILTIN {
Ok(Self::Builtin)
} else if text == Self::CONTRACT {
Ok(Self::Contract)
} else if text == Self::NULL {
Ok(Self::Null)
} else if text == Self::USER {
Ok(Self::User)
} else {
Ok(Self::Unknown)
}
}
pub fn from_address<T: AddressUtil>(
address_hex: &T,
) -> Result<Self, EncodingError> {
match address_hex.address_type_bits() {
address_util::TYPE_BITS_BUILTIN => {
if address_hex.is_null_address() {
Ok(Self::Null)
} else {
Ok(Self::Builtin)
}
}
address_util::TYPE_BITS_CONTRACT => Ok(Self::Contract),
address_util::TYPE_BITS_USER_ACCOUNT => Ok(Self::User),
_ => Ok(Self::Unknown),
}
}
pub fn to_str(&self) -> &'static str {
match self {
Self::Builtin => Self::BUILTIN,
Self::Contract => Self::CONTRACT,
Self::Null => Self::NULL,
Self::User => Self::USER,
Self::Unknown => Self::UNKNOWN,
}
}
}
impl ToString for AddressType {
fn to_string(&self) -> String { self.to_str().into() }
}