1use super::*;
2
3#[derive(Debug, PartialEq, Clone, DeserializeFromStr, SerializeDisplay)]
4pub enum Object {
5 Address(Address<NetworkUnchecked>),
6 Hash([u8; 32]),
7 InscriptionId(InscriptionId),
8 Integer(u128),
9 OutPoint(OutPoint),
10 Rune(SpacedRune),
11 Sat(Sat),
12 SatPoint(SatPoint),
13}
14
15impl FromStr for Object {
16 type Err = Error;
17
18 fn from_str(s: &str) -> Result<Self> {
19 use Representation::*;
20
21 match Representation::from_str(s)? {
22 Address => Ok(Self::Address(s.parse()?)),
23 Decimal | Degree | Percentile | Name => Ok(Self::Sat(s.parse()?)),
24 Hash => Ok(Self::Hash(
25 bitcoin::hashes::sha256::Hash::from_str(s)?.to_byte_array(),
26 )),
27 InscriptionId => Ok(Self::InscriptionId(s.parse()?)),
28 Integer => Ok(Self::Integer(s.parse()?)),
29 OutPoint => Ok(Self::OutPoint(s.parse()?)),
30 Rune => Ok(Self::Rune(s.parse()?)),
31 SatPoint => Ok(Self::SatPoint(s.parse()?)),
32 }
33 }
34}
35
36impl Display for Object {
37 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
38 match self {
39 Self::Address(address) => write!(f, "{}", address.clone().assume_checked()),
40 Self::Hash(hash) => {
41 for byte in hash {
42 write!(f, "{byte:02x}")?;
43 }
44 Ok(())
45 }
46 Self::InscriptionId(inscription_id) => write!(f, "{inscription_id}"),
47 Self::Integer(integer) => write!(f, "{integer}"),
48 Self::OutPoint(outpoint) => write!(f, "{outpoint}"),
49 Self::Rune(rune) => write!(f, "{rune}"),
50 Self::Sat(sat) => write!(f, "{sat}"),
51 Self::SatPoint(satpoint) => write!(f, "{satpoint}"),
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn from_str() {
62 #[track_caller]
63 fn case(s: &str, expected: Object) {
64 let actual = s.parse::<Object>().unwrap();
65 assert_eq!(actual, expected);
66 let round_trip = actual.to_string().parse::<Object>().unwrap();
67 assert_eq!(round_trip, expected);
68 }
69
70 assert_eq!(
71 "nvtdijuwxlp".parse::<Object>().unwrap(),
72 Object::Sat(Sat(0))
73 );
74 assert_eq!("a".parse::<Object>().unwrap(), Object::Sat(Sat::LAST));
75 assert_eq!(
76 "1.1".parse::<Object>().unwrap(),
77 Object::Sat(Sat(50 * COIN_VALUE + 1))
78 );
79 assert_eq!(
80 "1°0′0″0‴".parse::<Object>().unwrap(),
81 Object::Sat(Sat(2067187500000000))
82 );
83 assert_eq!("0%".parse::<Object>().unwrap(), Object::Sat(Sat(0)));
84
85 case("0", Object::Integer(0));
86
87 case(
88 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefi1",
89 Object::InscriptionId(
90 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefi1"
91 .parse()
92 .unwrap(),
93 ),
94 );
95
96 case(
97 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
98 Object::Hash([
99 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
100 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
101 0xcd, 0xef,
102 ]),
103 );
104 case(
105 "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
106 Object::Address(
107 "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
108 .parse()
109 .unwrap(),
110 ),
111 );
112 case(
113 "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
114 Object::Address(
115 "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4"
116 .parse()
117 .unwrap(),
118 ),
119 );
120 case(
121 "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
122 Object::Address(
123 "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy"
124 .parse()
125 .unwrap(),
126 ),
127 );
128 case(
129 "TB1QQQQQP399ET2XYGDJ5XREQHJJVCMZHXW4AYWXECJDZEW6HYLGVSESRXH6HY",
130 Object::Address(
131 "TB1QQQQQP399ET2XYGDJ5XREQHJJVCMZHXW4AYWXECJDZEW6HYLGVSESRXH6HY"
132 .parse()
133 .unwrap(),
134 ),
135 );
136 case(
137 "bcrt1qs758ursh4q9z627kt3pp5yysm78ddny6txaqgw",
138 Object::Address(
139 "bcrt1qs758ursh4q9z627kt3pp5yysm78ddny6txaqgw"
140 .parse()
141 .unwrap(),
142 ),
143 );
144 case(
145 "BCRT1QS758URSH4Q9Z627KT3PP5YYSM78DDNY6TXAQGW",
146 Object::Address(
147 "BCRT1QS758URSH4Q9Z627KT3PP5YYSM78DDNY6TXAQGW"
148 .parse()
149 .unwrap(),
150 ),
151 );
152 case(
153 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123",
154 Object::OutPoint(
155 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123"
156 .parse()
157 .unwrap(),
158 ),
159 );
160 case(
161 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF:123",
162 Object::OutPoint(
163 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF:123"
164 .parse()
165 .unwrap(),
166 ),
167 );
168 case(
169 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123:456",
170 Object::SatPoint(
171 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123:456"
172 .parse()
173 .unwrap(),
174 ),
175 );
176 case(
177 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF:123:456",
178 Object::SatPoint(
179 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF:123:456"
180 .parse()
181 .unwrap(),
182 ),
183 );
184 case(
185 "A",
186 Object::Rune(SpacedRune {
187 rune: Rune(0),
188 spacers: 0,
189 }),
190 );
191 case(
192 "A•A",
193 Object::Rune(SpacedRune {
194 rune: Rune(26),
195 spacers: 1,
196 }),
197 );
198 }
199}