bark/persist/adaptor/
sort.rs1use bitcoin::Amount;
2use chrono::{DateTime, Local};
3
4use crate::vtxo::VtxoStateKind;
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
17pub struct SortKey(Vec<u8>);
18
19impl SortKey {
20 pub fn as_bytes(&self) -> &[u8] {
22 &self.0
23 }
24
25 pub fn from_bytes(bytes: Vec<u8>) -> Self {
27 Self(bytes)
28 }
29
30 pub fn builder() -> SortKeyBuilder {
32 SortKeyBuilder(Vec::new())
33 }
34
35 pub fn u32_asc(n: u32) -> Self {
37 Self::builder().u32_asc(n).build()
38 }
39
40 pub fn u64_desc(n: u64) -> Self {
42 Self::builder().u64_desc(n).build()
43 }
44}
45
46#[derive(Debug, Clone, Default)]
63pub struct SortKeyBuilder(Vec<u8>);
64
65impl SortKeyBuilder {
66 pub fn u8_asc(mut self, n: u8) -> Self {
67 self.0.push(n);
68 self
69 }
70
71 pub fn u32_asc(mut self, n: u32) -> Self {
73 self.0.extend_from_slice(&n.to_be_bytes());
74 self
75 }
76
77 pub fn u64_desc(mut self, n: u64) -> Self {
79 self.0.extend_from_slice(&(!n).to_be_bytes());
80 self
81 }
82
83 pub fn build(self) -> SortKey {
85 SortKey(self.0)
86 }
87}
88
89pub(crate) fn vtxo_sort_key(vtxo_state: VtxoStateKind, expiry_height: u32, amount: Amount) -> SortKey {
90 SortKey::builder()
93 .u8_asc(vtxo_state.as_byte())
94 .u32_asc(expiry_height)
95 .u64_desc(amount.to_sat())
96 .build()
97}
98
99pub(crate) fn movement_sort_key(created_at: &DateTime<Local>) -> SortKey {
100 SortKey::u64_desc(created_at.timestamp_millis() as u64)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn sort_key_u64() {
110 let k1 = SortKey::builder().u32_asc(1).build();
111 let k2 = SortKey::builder().u32_asc(2).build();
112 let k3 = SortKey::builder().u32_asc(3).build();
113
114 assert!(k1 < k2);
115 assert!(k2 < k3);
116 assert!(k1 < k3);
117 }
118
119 #[test]
120 fn sort_key_u64_desc() {
121 let k1 = SortKey::builder().u64_desc(1).build();
122 let k2 = SortKey::builder().u64_desc(2).build();
123 let k3 = SortKey::builder().u64_desc(3).build();
124
125 assert!(k1 > k2);
126 assert!(k2 > k3);
127 assert!(k1 > k3);
128 }
129
130 #[test]
131 fn sort_key_composite() {
132 let make_key = |height: u32, amount: u64| {
134 SortKey::builder()
135 .u32_asc(height)
136 .u64_desc(amount)
137 .build()
138 };
139
140 let k1 = make_key(100, 1000);
142 let k2 = make_key(100, 500);
143 assert!(k1 < k2); let k3 = make_key(50, 100);
147 assert!(k3 < k1);
148 assert!(k3 < k2);
149
150 let k4 = make_key(150, 100);
152 assert!(k4 > k1);
153 assert!(k4 > k2);
154 assert!(k4 > k3);
155 }
156}