TLA Line data Source code
1 : use anyhow::{bail, Result};
2 : use byteorder::{ByteOrder, BE};
3 : use serde::{Deserialize, Serialize};
4 : use std::fmt;
5 :
6 : /// Key used in the Repository kv-store.
7 : ///
8 : /// The Repository treats this as an opaque struct, but see the code in pgdatadir_mapping.rs
9 : /// for what we actually store in these fields.
10 CBC 201354926 : #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
11 : pub struct Key {
12 : pub field1: u8,
13 : pub field2: u32,
14 : pub field3: u32,
15 : pub field4: u32,
16 : pub field5: u8,
17 : pub field6: u32,
18 : }
19 :
20 : pub const KEY_SIZE: usize = 18;
21 :
22 : impl Key {
23 : /// 'field2' is used to store tablespaceid for relations and small enum numbers for other relish.
24 : /// As long as Neon does not support tablespace (because of lack of access to local file system),
25 : /// we can assume that only some predefined namespace OIDs are used which can fit in u16
26 78069726 : pub fn to_i128(&self) -> i128 {
27 78069726 : assert!(self.field2 < 0xFFFF || self.field2 == 0xFFFFFFFF || self.field2 == 0x22222222);
28 78069726 : (((self.field1 & 0xf) as i128) << 120)
29 78069726 : | (((self.field2 & 0xFFFF) as i128) << 104)
30 78069726 : | ((self.field3 as i128) << 72)
31 78069726 : | ((self.field4 as i128) << 40)
32 78069726 : | ((self.field5 as i128) << 32)
33 78069726 : | self.field6 as i128
34 78069726 : }
35 :
36 12150865 : pub const fn from_i128(x: i128) -> Self {
37 12150865 : Key {
38 12150865 : field1: ((x >> 120) & 0xf) as u8,
39 12150865 : field2: ((x >> 104) & 0xFFFF) as u32,
40 12150865 : field3: (x >> 72) as u32,
41 12150865 : field4: (x >> 40) as u32,
42 12150865 : field5: (x >> 32) as u8,
43 12150865 : field6: x as u32,
44 12150865 : }
45 12150865 : }
46 :
47 18156039 : pub fn next(&self) -> Key {
48 18156039 : self.add(1)
49 18156039 : }
50 :
51 18161850 : pub fn add(&self, x: u32) -> Key {
52 18161850 : let mut key = *self;
53 18161850 :
54 18161850 : let r = key.field6.overflowing_add(x);
55 18161850 : key.field6 = r.0;
56 18161850 : if r.1 {
57 1323329 : let r = key.field5.overflowing_add(1);
58 1323329 : key.field5 = r.0;
59 1323329 : if r.1 {
60 UBC 0 : let r = key.field4.overflowing_add(1);
61 0 : key.field4 = r.0;
62 0 : if r.1 {
63 0 : let r = key.field3.overflowing_add(1);
64 0 : key.field3 = r.0;
65 0 : if r.1 {
66 0 : let r = key.field2.overflowing_add(1);
67 0 : key.field2 = r.0;
68 0 : if r.1 {
69 0 : let r = key.field1.overflowing_add(1);
70 0 : key.field1 = r.0;
71 0 : assert!(!r.1);
72 0 : }
73 0 : }
74 0 : }
75 CBC 1323329 : }
76 16838521 : }
77 18161850 : key
78 18161850 : }
79 :
80 16792843 : pub fn from_slice(b: &[u8]) -> Self {
81 16792843 : Key {
82 16792843 : field1: b[0],
83 16792843 : field2: u32::from_be_bytes(b[1..5].try_into().unwrap()),
84 16792843 : field3: u32::from_be_bytes(b[5..9].try_into().unwrap()),
85 16792843 : field4: u32::from_be_bytes(b[9..13].try_into().unwrap()),
86 16792843 : field5: b[13],
87 16792843 : field6: u32::from_be_bytes(b[14..18].try_into().unwrap()),
88 16792843 : }
89 16792843 : }
90 :
91 62181926 : pub fn write_to_byte_slice(&self, buf: &mut [u8]) {
92 62181926 : buf[0] = self.field1;
93 62181926 : BE::write_u32(&mut buf[1..5], self.field2);
94 62181926 : BE::write_u32(&mut buf[5..9], self.field3);
95 62181926 : BE::write_u32(&mut buf[9..13], self.field4);
96 62181926 : buf[13] = self.field5;
97 62181926 : BE::write_u32(&mut buf[14..18], self.field6);
98 62181926 : }
99 : }
100 :
101 : impl fmt::Display for Key {
102 2937069 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 2937069 : write!(
104 2937069 : f,
105 2937069 : "{:02X}{:08X}{:08X}{:08X}{:02X}{:08X}",
106 2937069 : self.field1, self.field2, self.field3, self.field4, self.field5, self.field6
107 2937069 : )
108 2937069 : }
109 : }
110 :
111 : impl Key {
112 : pub const MIN: Key = Key {
113 : field1: u8::MIN,
114 : field2: u32::MIN,
115 : field3: u32::MIN,
116 : field4: u32::MIN,
117 : field5: u8::MIN,
118 : field6: u32::MIN,
119 : };
120 : pub const MAX: Key = Key {
121 : field1: u8::MAX,
122 : field2: u32::MAX,
123 : field3: u32::MAX,
124 : field4: u32::MAX,
125 : field5: u8::MAX,
126 : field6: u32::MAX,
127 : };
128 :
129 215201 : pub fn from_hex(s: &str) -> Result<Self> {
130 215201 : if s.len() != 36 {
131 UBC 0 : bail!("parse error");
132 CBC 215201 : }
133 215201 : Ok(Key {
134 215201 : field1: u8::from_str_radix(&s[0..2], 16)?,
135 215201 : field2: u32::from_str_radix(&s[2..10], 16)?,
136 215201 : field3: u32::from_str_radix(&s[10..18], 16)?,
137 215201 : field4: u32::from_str_radix(&s[18..26], 16)?,
138 215201 : field5: u8::from_str_radix(&s[26..28], 16)?,
139 215201 : field6: u32::from_str_radix(&s[28..36], 16)?,
140 : })
141 215201 : }
142 : }
143 :
144 22558333 : pub fn is_rel_block_key(key: &Key) -> bool {
145 22558333 : key.field1 == 0x00 && key.field4 != 0 && key.field6 != 0xffffffff
146 22558333 : }
147 :
148 : impl std::str::FromStr for Key {
149 : type Err = anyhow::Error;
150 :
151 7 : fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
152 7 : Self::from_hex(s)
153 7 : }
154 : }
155 :
156 : #[cfg(test)]
157 : mod tests {
158 : use std::str::FromStr;
159 :
160 : use crate::key::Key;
161 :
162 : use rand::Rng;
163 : use rand::SeedableRng;
164 :
165 1 : #[test]
166 1 : fn display_fromstr_bijection() {
167 1 : let mut rng = rand::rngs::StdRng::seed_from_u64(42);
168 1 :
169 1 : let key = Key {
170 1 : field1: rng.gen(),
171 1 : field2: rng.gen(),
172 1 : field3: rng.gen(),
173 1 : field4: rng.gen(),
174 1 : field5: rng.gen(),
175 1 : field6: rng.gen(),
176 1 : };
177 1 :
178 1 : assert_eq!(key, Key::from_str(&format!("{key}")).unwrap());
179 1 : }
180 : }
|