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