use std::sync::atomic::{AtomicU8, Ordering};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
use super::{Address, Error, MAINNET_PREFIX, TESTNET_PREFIX};
static ATOMIC_NETWORK: AtomicU8 = AtomicU8::new(0);
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
#[repr(u8)]
#[cfg_attr(feature = "arb", derive(arbitrary::Arbitrary))]
#[derive(Default)]
pub enum Network {
#[default]
Mainnet = 0,
Testnet = 1,
}
impl Network {
pub(super) fn to_prefix(self) -> &'static str {
match self {
Network::Mainnet => MAINNET_PREFIX,
Network::Testnet => TESTNET_PREFIX,
}
}
pub(super) fn from_prefix(s: &str) -> Result<Self, Error> {
match s {
MAINNET_PREFIX => Ok(Network::Mainnet),
TESTNET_PREFIX => Ok(Network::Testnet),
_ => Err(Error::UnknownNetwork),
}
}
pub fn parse_address(self, addr: &str) -> Result<Address, Error> {
let (addr, network) = super::parse_address(addr)?;
if network != self {
return Err(Error::UnknownNetwork);
}
Ok(addr)
}
}
pub fn current_network() -> Network {
Network::from_u8(ATOMIC_NETWORK.load(Ordering::Relaxed)).unwrap_or_default()
}
pub fn set_current_network(network: Network) {
ATOMIC_NETWORK.store(network.to_u8().unwrap_or_default(), Ordering::Relaxed)
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
use crate::address::Address;
use rusty_fork::rusty_fork_test;
rusty_fork_test! {
#[test]
fn set_network() {
assert_eq!(current_network(), Network::default());
assert_eq!(Network::default(), Network::Mainnet);
let addr1 = Address::from_str("f01");
Address::from_str("t01").expect_err("should have failed to parse testnet address");
assert_eq!(
addr1,
Network::Testnet.parse_address("t01"),
"parsing an explicit address should still work"
);
set_current_network(Network::Testnet);
let addr2 = Address::from_str("t01");
Address::from_str("f01").expect_err("should have failed to parse testnet address");
assert_eq!(addr1, addr2)
}
}
}