1use std::ops::{Add, AddAssign};
2
3use byteview::ByteView;
4use derive_more::{Deref, DerefMut};
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use vecdb::{CheckedSub, Formattable, Pco, PrintableIndex};
8
9use super::StoredU32;
10
11#[derive(
12 Debug,
13 PartialEq,
14 Eq,
15 PartialOrd,
16 Ord,
17 Clone,
18 Copy,
19 Deref,
20 DerefMut,
21 Default,
22 Serialize,
23 Deserialize,
24 Pco,
25 JsonSchema,
26 Hash,
27)]
28pub struct TxIndex(u32);
29
30impl TxIndex {
31 pub const ZERO: Self = Self(0);
32 pub const COINBASE: Self = Self(u32::MAX);
33
34 pub fn new(tx_index: u32) -> Self {
35 Self(tx_index)
36 }
37
38 pub fn incremented(self) -> Self {
39 Self(*self + 1)
40 }
41
42 pub fn to_be_bytes(&self) -> [u8; 4] {
43 self.0.to_be_bytes()
44 }
45
46 pub fn to_ne_bytes(&self) -> [u8; 4] {
47 self.0.to_ne_bytes()
48 }
49
50 #[inline(always)]
51 pub fn is_coinbase(self) -> bool {
52 self == Self::COINBASE
53 }
54
55 #[inline(always)]
56 pub fn is_not_coinbase(self) -> bool {
57 self != Self::COINBASE
58 }
59}
60
61impl Add<TxIndex> for TxIndex {
62 type Output = Self;
63 fn add(self, rhs: TxIndex) -> Self::Output {
64 Self(self.0 + rhs.0)
65 }
66}
67
68impl Add<usize> for TxIndex {
69 type Output = Self;
70 fn add(self, rhs: usize) -> Self::Output {
71 Self(self.0 + rhs as u32)
72 }
73}
74
75impl AddAssign<TxIndex> for TxIndex {
76 fn add_assign(&mut self, rhs: TxIndex) {
77 self.0 += rhs.0
78 }
79}
80
81impl CheckedSub<TxIndex> for TxIndex {
82 fn checked_sub(self, rhs: TxIndex) -> Option<Self> {
83 self.0.checked_sub(rhs.0).map(TxIndex::from)
84 }
85}
86
87impl From<u32> for TxIndex {
88 #[inline]
89 fn from(value: u32) -> Self {
90 Self(value)
91 }
92}
93
94impl From<TxIndex> for u32 {
95 #[inline]
96 fn from(value: TxIndex) -> Self {
97 value.0
98 }
99}
100
101impl From<u64> for TxIndex {
102 #[inline]
103 fn from(value: u64) -> Self {
104 Self(value as u32)
105 }
106}
107impl From<TxIndex> for u64 {
108 #[inline]
109 fn from(value: TxIndex) -> Self {
110 value.0 as u64
111 }
112}
113
114impl From<usize> for TxIndex {
115 #[inline]
116 fn from(value: usize) -> Self {
117 Self(value as u32)
118 }
119}
120impl From<TxIndex> for usize {
121 #[inline]
122 fn from(value: TxIndex) -> Self {
123 value.0 as usize
124 }
125}
126
127impl From<ByteView> for TxIndex {
128 #[inline(always)]
129 fn from(value: ByteView) -> Self {
130 Self(u32::from_be_bytes((&*value).try_into().unwrap()))
131 }
132}
133impl From<TxIndex> for ByteView {
134 #[inline(always)]
135 fn from(value: TxIndex) -> Self {
136 ByteView::from(&value)
137 }
138}
139impl From<&TxIndex> for ByteView {
140 #[inline(always)]
141 fn from(value: &TxIndex) -> Self {
142 Self::new(&value.to_be_bytes())
143 }
144}
145
146impl From<TxIndex> for StoredU32 {
147 #[inline]
148 fn from(value: TxIndex) -> Self {
149 Self::from(value.0)
150 }
151}
152
153impl PrintableIndex for TxIndex {
154 fn to_string() -> &'static str {
155 "tx_index"
156 }
157
158 fn to_possible_strings() -> &'static [&'static str] {
159 &["tx", "tx_index"]
160 }
161}
162
163impl std::fmt::Display for TxIndex {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 let mut buf = itoa::Buffer::new();
166 let str = buf.format(self.0);
167 f.write_str(str)
168 }
169}
170
171impl Formattable for TxIndex {
172 #[inline(always)]
173 fn write_to(&self, buf: &mut Vec<u8>) {
174 let mut b = itoa::Buffer::new();
175 buf.extend_from_slice(b.format(self.0).as_bytes());
176 }
177}