1use core::fmt;
4use core::str::FromStr;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
8#[non_exhaustive]
9pub enum Network {
10 #[default]
12 Mainnet,
13 Testnet,
15}
16
17impl Network {
18 #[inline]
20 #[must_use]
21 pub const fn coin_type(self) -> u32 {
22 match self {
23 Self::Mainnet => 0,
24 Self::Testnet => 1,
25 }
26 }
27
28 #[inline]
30 #[must_use]
31 pub const fn name(self) -> &'static str {
32 match self {
33 Self::Mainnet => "mainnet",
34 Self::Testnet => "testnet",
35 }
36 }
37}
38
39impl fmt::Display for Network {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.write_str(self.name())
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
47#[non_exhaustive]
48pub struct ParseNetworkError;
49
50impl fmt::Display for ParseNetworkError {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 f.write_str("invalid network, expected: mainnet or testnet")
53 }
54}
55
56#[cfg(feature = "std")]
57impl std::error::Error for ParseNetworkError {}
58
59impl FromStr for Network {
60 type Err = ParseNetworkError;
61
62 fn from_str(s: &str) -> Result<Self, Self::Err> {
63 match s.to_lowercase().as_str() {
64 "mainnet" | "main" | "bitcoin" => Ok(Self::Mainnet),
65 "testnet" | "test" | "testnet3" | "testnet4" => Ok(Self::Testnet),
66 _ => Err(ParseNetworkError),
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn network_from_str() {
77 assert_eq!("mainnet".parse::<Network>().unwrap(), Network::Mainnet);
78 assert_eq!("main".parse::<Network>().unwrap(), Network::Mainnet);
79 assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Mainnet);
80 assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
81 assert_eq!("test".parse::<Network>().unwrap(), Network::Testnet);
82 }
83
84 #[test]
85 fn network_from_str_case_insensitive() {
86 assert_eq!("MAINNET".parse::<Network>().unwrap(), Network::Mainnet);
87 assert_eq!("TESTNET".parse::<Network>().unwrap(), Network::Testnet);
88 }
89
90 #[test]
91 fn network_from_str_invalid() {
92 assert!("invalid".parse::<Network>().is_err());
93 assert!("".parse::<Network>().is_err());
94 }
95
96 #[test]
97 fn network_coin_type() {
98 assert_eq!(Network::Mainnet.coin_type(), 0);
99 assert_eq!(Network::Testnet.coin_type(), 1);
100 }
101
102 #[test]
103 fn network_default() {
104 assert_eq!(Network::default(), Network::Mainnet);
105 }
106
107 #[test]
108 fn network_display() {
109 assert_eq!(Network::Mainnet.to_string(), "mainnet");
110 assert_eq!(Network::Testnet.to_string(), "testnet");
111 }
112}