1#[cfg(feature = "pub-response-field")]
4pub(crate) mod pb;
5
6#[cfg(not(feature = "pub-response-field"))]
7mod pb;
8
9pub mod auth;
10pub mod cluster;
11pub mod election;
12pub mod kv;
13pub mod lease;
14pub mod lock;
15pub mod maintenance;
16pub mod watch;
17
18use crate::error::Result;
19use pb::etcdserverpb::ResponseHeader as PbResponseHeader;
20use pb::mvccpb::KeyValue as PbKeyValue;
21
22#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
24#[derive(Debug, Clone)]
25#[repr(transparent)]
26pub struct ResponseHeader(PbResponseHeader);
27
28impl ResponseHeader {
29 #[inline]
31 pub(crate) const fn new(header: PbResponseHeader) -> Self {
32 Self(header)
33 }
34
35 #[inline]
37 pub const fn cluster_id(&self) -> u64 {
38 self.0.cluster_id
39 }
40
41 #[inline]
43 pub const fn member_id(&self) -> u64 {
44 self.0.member_id
45 }
46
47 #[inline]
52 pub const fn revision(&self) -> i64 {
53 self.0.revision
54 }
55
56 #[inline]
58 pub const fn raft_term(&self) -> u64 {
59 self.0.raft_term
60 }
61}
62
63impl From<&PbResponseHeader> for &ResponseHeader {
64 #[inline]
65 fn from(src: &PbResponseHeader) -> Self {
66 unsafe { &*(src as *const _ as *const ResponseHeader) }
67 }
68}
69
70#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
72#[derive(Debug, Clone)]
73#[repr(transparent)]
74pub struct KeyValue(PbKeyValue);
75
76impl KeyValue {
77 #[inline]
79 pub(crate) const fn new(kv: PbKeyValue) -> Self {
80 Self(kv)
81 }
82
83 #[inline]
85 pub fn key(&self) -> &[u8] {
86 &self.0.key
87 }
88
89 #[inline]
91 pub fn key_str(&self) -> Result<&str> {
92 std::str::from_utf8(self.key()).map_err(From::from)
93 }
94
95 #[inline]
102 pub unsafe fn key_str_unchecked(&self) -> &str {
103 std::str::from_utf8_unchecked(self.key())
104 }
105
106 #[inline]
108 pub fn value(&self) -> &[u8] {
109 &self.0.value
110 }
111
112 #[inline]
114 pub fn value_str(&self) -> Result<&str> {
115 std::str::from_utf8(self.value()).map_err(From::from)
116 }
117
118 #[inline]
125 pub unsafe fn value_str_unchecked(&self) -> &str {
126 std::str::from_utf8_unchecked(self.value())
127 }
128
129 pub fn into_key_value(self) -> (Vec<u8>, Vec<u8>) {
131 (self.0.key, self.0.value)
132 }
133
134 #[inline]
136 pub const fn create_revision(&self) -> i64 {
137 self.0.create_revision
138 }
139
140 #[inline]
142 pub const fn mod_revision(&self) -> i64 {
143 self.0.mod_revision
144 }
145
146 #[inline]
150 pub const fn version(&self) -> i64 {
151 self.0.version
152 }
153
154 #[inline]
158 pub const fn lease(&self) -> i64 {
159 self.0.lease
160 }
161}
162
163impl From<&PbKeyValue> for &KeyValue {
164 #[inline]
165 fn from(src: &PbKeyValue) -> Self {
166 unsafe { &*(src as *const _ as *const KeyValue) }
167 }
168}
169
170impl From<&mut PbKeyValue> for &mut KeyValue {
171 #[inline]
172 fn from(src: &mut PbKeyValue) -> Self {
173 unsafe { &mut *(src as *mut _ as *mut KeyValue) }
174 }
175}
176
177#[inline]
179fn get_prefix(key: &[u8]) -> Vec<u8> {
180 for (i, v) in key.iter().enumerate().rev() {
181 if *v < 0xFF {
182 let mut end = Vec::from(&key[..=i]);
183 end[i] = *v + 1;
184 return end;
185 }
186 }
187
188 vec![0]
190}
191
192#[derive(Debug, Default, Clone)]
194struct KeyRange {
195 key: Vec<u8>,
196 range_end: Vec<u8>,
197 with_prefix: bool,
198 with_from_key: bool,
199 with_all_keys: bool,
200}
201
202impl KeyRange {
203 #[inline]
204 pub const fn new() -> Self {
205 KeyRange {
206 key: Vec::new(),
207 range_end: Vec::new(),
208 with_prefix: false,
209 with_from_key: false,
210 with_all_keys: false,
211 }
212 }
213
214 #[inline]
216 pub fn with_key(&mut self, key: impl Into<Vec<u8>>) {
217 self.key = key.into();
218 }
219
220 #[inline]
223 pub fn with_range(&mut self, end_key: impl Into<Vec<u8>>) {
224 self.range_end = end_key.into();
225 self.with_prefix = false;
226 self.with_from_key = false;
227 self.with_all_keys = false;
228 }
229
230 #[inline]
232 pub fn with_from_key(&mut self) {
233 self.with_from_key = true;
234 self.with_prefix = false;
235 self.with_all_keys = false;
236 }
237
238 #[inline]
240 pub fn with_prefix(&mut self) {
241 self.with_prefix = true;
242 self.with_from_key = false;
243 self.with_all_keys = false;
244 }
245
246 #[inline]
248 pub fn with_all_keys(&mut self) {
249 self.with_all_keys = true;
250 self.with_prefix = false;
251 self.with_from_key = false;
252 }
253
254 #[inline]
256 pub fn build(mut self) -> (Vec<u8>, Vec<u8>) {
257 if self.with_all_keys {
258 self.key = vec![b'\0'];
259 self.range_end = vec![b'\0'];
260 } else if self.with_from_key {
261 if self.key.is_empty() {
262 self.key = vec![b'\0'];
263 }
264 self.range_end = vec![b'\0'];
265 } else if self.with_prefix {
266 if self.key.is_empty() {
267 self.key = vec![b'\0'];
268 self.range_end = vec![b'\0'];
269 } else {
270 self.range_end = get_prefix(&self.key);
271 }
272 }
273
274 (self.key, self.range_end)
275 }
276}
277
278#[cfg(test)]
279mod tests {
280 use super::*;
281
282 #[test]
283 fn test_get_prefix() {
284 assert_eq!(get_prefix(b"foo1").as_slice(), b"foo2");
285 assert_eq!(get_prefix(b"\xFF").as_slice(), b"\0");
286 assert_eq!(get_prefix(b"foo\xFF").as_slice(), b"fop");
287 }
288}