ord/
object.rs

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}