libpijul_compat/backend/
key.rs1use super::patch_id::*;
2use bs58;
3use sanakirja::{Alignment, Representable};
4use std;
5use Hash;
6
7const LINE_ID_SIZE: usize = 8;
8pub const KEY_SIZE: usize = PATCH_ID_SIZE + LINE_ID_SIZE;
9
10pub const ROOT_KEY: Key<PatchId> = Key {
12 patch: ROOT_PATCH_ID,
13 line: LineId([0; LINE_ID_SIZE]),
14};
15
16use hex::ToHex;
17use std::fmt::Write;
18impl ToHex for Key<PatchId> {
19 fn write_hex<W: Write>(&self, w: &mut W) -> std::fmt::Result {
20 self.patch.write_hex(w)?;
21 self.line.write_hex(w)
22 }
23 fn write_hex_upper<W: Write>(&self, w: &mut W) -> std::fmt::Result {
24 self.patch.write_hex(w)?;
25 self.line.write_hex(w)
26 }
27}
28
29impl Key<PatchId> {
30 pub fn to_base58(&self) -> String {
31 self.patch.to_base58() + &bs58::encode(&self.line.0).into_string()
32 }
33 pub fn to_hex(&self) -> String {
34 let mut s = String::new();
35 self.write_hex(&mut s).unwrap();
36 s
37 }
38}
39
40impl Key<Hash> {
41 pub fn to_base58(&self) -> String {
42 self.patch.to_base58() + &bs58::encode(&self.line.0).into_string()
43 }
44}
45
46impl Key<PatchId> {
47 pub fn is_root(&self) -> bool {
49 self == &ROOT_KEY
50 }
51
52 pub fn from_hex(hex: &str) -> Option<Self> {
54 let mut s = [0; KEY_SIZE];
55 if super::from_hex(hex, &mut s) {
56 Some(unsafe { std::mem::transmute(s) })
57 } else {
58 None
59 }
60 }
61}
62
63#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
69pub struct LineId([u8; LINE_ID_SIZE]);
70
71impl ToHex for LineId {
72 fn write_hex<W: Write>(&self, w: &mut W) -> std::fmt::Result {
73 let mut h = String::new();
74 self.0.write_hex(&mut h)?;
75 w.write_str(h.trim_right_matches('0'))
76 }
77 fn write_hex_upper<W: Write>(&self, w: &mut W) -> std::fmt::Result {
78 let mut h = String::new();
79 self.0.write_hex_upper(&mut h)?;
80 w.write_str(h.trim_right_matches('0'))
81 }
82}
83
84impl std::fmt::Debug for LineId {
85 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
86 write!(fmt, "LineId(0x{})", self.to_hex())
87 }
88}
89
90impl LineId {
91 pub fn new() -> LineId {
93 LineId([0; LINE_ID_SIZE])
94 }
95 pub fn is_root(&self) -> bool {
97 self.0.iter().all(|x| *x == 0)
98 }
99 pub fn to_hex(&self) -> String {
100 let mut s = String::new();
101 self.write_hex(&mut s).unwrap();
102 s
103 }
104}
105use byteorder::{ByteOrder, LittleEndian};
106impl std::ops::Add<usize> for LineId {
107 type Output = LineId;
108 fn add(self, x: usize) -> Self::Output {
109 let a = LittleEndian::read_u64(&self.0);
110 let mut b = LineId::new();
111 LittleEndian::write_u64(&mut b.0, a + x as u64);
112 b
113 }
114}
115impl std::ops::AddAssign<usize> for LineId {
116 fn add_assign(&mut self, x: usize) {
117 *self = self.clone() + x
118 }
119}
120
121#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
124pub struct Key<H> {
125 pub patch: H,
127 pub line: LineId,
131}
132
133#[test]
134fn test_key_alignment() {
135 assert_eq!(std::mem::size_of::<Key<PatchId>>(), 16)
136}
137
138impl<T> AsRef<LineId> for Key<T> {
139 fn as_ref(&self) -> &LineId {
140 &self.line
141 }
142}
143
144impl<T: Clone> Key<Option<T>> {
145 pub fn unwrap_patch(&self) -> Key<T> {
146 Key {
147 patch: self.patch.as_ref().unwrap().clone(),
148 line: self.line.clone(),
149 }
150 }
151}
152
153impl Representable for Key<PatchId> {
154 fn alignment() -> Alignment {
155 Alignment::B1
156 }
157 fn onpage_size(&self) -> u16 {
158 (PATCH_ID_SIZE + LINE_ID_SIZE) as u16
159 }
160 unsafe fn write_value(&self, p: *mut u8) {
161 trace!("write_value {:?}", p);
162 std::ptr::copy(self as *const Key<PatchId> as *const u8, p, KEY_SIZE)
163 }
164 unsafe fn read_value(p: *const u8) -> Self {
165 trace!("read_value {:?}", p);
166 let mut k = std::mem::uninitialized();
167 std::ptr::copy(p, (&mut k) as *mut Key<PatchId> as *mut u8, 16);
168 k
169 }
170 unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
171 self.cmp(&x)
172 }
173 type PageOffsets = std::iter::Empty<u64>;
174 fn page_offsets(&self) -> Self::PageOffsets {
175 std::iter::empty()
176 }
177}