1pub use crate::rpc::pb::etcdserverpb::compare::CompareResult as CompareOp;
4pub use crate::rpc::pb::etcdserverpb::range_request::{SortOrder, SortTarget};
5
6use crate::auth::AuthService;
7use crate::error::Result;
8use crate::intercept::InterceptedChannel;
9use crate::rpc::pb::etcdserverpb::compare::{CompareTarget, TargetUnion};
10use crate::rpc::pb::etcdserverpb::kv_client::KvClient as PbKvClient;
11use crate::rpc::pb::etcdserverpb::request_op::Request as PbTxnOp;
12use crate::rpc::pb::etcdserverpb::response_op::Response as PbTxnOpResponse;
13use crate::rpc::pb::etcdserverpb::{
14 CompactionRequest as PbCompactionRequest, CompactionRequest,
15 CompactionResponse as PbCompactionResponse, Compare as PbCompare,
16 DeleteRangeRequest as PbDeleteRequest, DeleteRangeRequest,
17 DeleteRangeResponse as PbDeleteResponse, PutRequest as PbPutRequest,
18 PutResponse as PbPutResponse, RangeRequest as PbRangeRequest, RangeResponse as PbRangeResponse,
19 RequestOp as PbTxnRequestOp, TxnRequest as PbTxnRequest, TxnResponse as PbTxnResponse,
20};
21use crate::rpc::{get_prefix, KeyRange, KeyValue, ResponseHeader};
22use crate::vec::VecExt;
23use http::HeaderValue;
24use std::mem::ManuallyDrop;
25use std::sync::{Arc, RwLock};
26use tonic::{IntoRequest, Request};
27
28#[repr(transparent)]
30#[derive(Clone)]
31pub struct KvClient {
32 inner: PbKvClient<AuthService<InterceptedChannel>>,
33}
34
35impl KvClient {
36 #[inline]
38 pub(crate) fn new(
39 channel: InterceptedChannel,
40 auth_token: Arc<RwLock<Option<HeaderValue>>>,
41 ) -> Self {
42 let inner = PbKvClient::new(AuthService::new(channel, auth_token));
43 Self { inner }
44 }
45
46 pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
50 self.inner = self.inner.max_decoding_message_size(limit);
51 self
52 }
53
54 pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
58 self.inner = self.inner.max_encoding_message_size(limit);
59 self
60 }
61
62 #[inline]
66 pub async fn put(
67 &mut self,
68 key: impl Into<Vec<u8>>,
69 value: impl Into<Vec<u8>>,
70 options: Option<PutOptions>,
71 ) -> Result<PutResponse> {
72 let resp = self
73 .inner
74 .put(options.unwrap_or_default().with_kv(key, value))
75 .await?
76 .into_inner();
77 Ok(PutResponse::new(resp))
78 }
79
80 #[inline]
82 pub async fn get(
83 &mut self,
84 key: impl Into<Vec<u8>>,
85 options: Option<GetOptions>,
86 ) -> Result<GetResponse> {
87 let resp = self
88 .inner
89 .range(options.unwrap_or_default().with_key(key.into()))
90 .await?
91 .into_inner();
92 Ok(GetResponse::new(resp))
93 }
94
95 #[inline]
97 pub async fn delete(
98 &mut self,
99 key: impl Into<Vec<u8>>,
100 options: Option<DeleteOptions>,
101 ) -> Result<DeleteResponse> {
102 let resp = self
103 .inner
104 .delete_range(options.unwrap_or_default().with_key(key.into()))
105 .await?
106 .into_inner();
107 Ok(DeleteResponse::new(resp))
108 }
109
110 #[inline]
114 pub async fn compact(
115 &mut self,
116 revision: i64,
117 options: Option<CompactionOptions>,
118 ) -> Result<CompactionResponse> {
119 let resp = self
120 .inner
121 .compact(options.unwrap_or_default().with_revision(revision))
122 .await?
123 .into_inner();
124 Ok(CompactionResponse::new(resp))
125 }
126
127 #[inline]
132 pub async fn txn(&mut self, txn: Txn) -> Result<TxnResponse> {
133 let resp = self.inner.txn(txn).await?.into_inner();
134 Ok(TxnResponse::new(resp))
135 }
136}
137
138#[derive(Debug, Default, Clone)]
140#[repr(transparent)]
141pub struct PutOptions(PbPutRequest);
142
143impl PutOptions {
144 #[inline]
146 fn with_kv(mut self, key: impl Into<Vec<u8>>, value: impl Into<Vec<u8>>) -> Self {
147 self.0.key = key.into();
148 self.0.value = value.into();
149 self
150 }
151
152 #[inline]
154 pub const fn new() -> Self {
155 Self(PbPutRequest {
156 key: Vec::new(),
157 value: Vec::new(),
158 lease: 0,
159 prev_kv: false,
160 ignore_value: false,
161 ignore_lease: false,
162 })
163 }
164
165 #[inline]
168 pub const fn with_lease(mut self, lease: i64) -> Self {
169 self.0.lease = lease;
170 self
171 }
172
173 #[inline]
176 pub const fn with_prev_key(mut self) -> Self {
177 self.0.prev_kv = true;
178 self
179 }
180
181 #[inline]
184 pub const fn with_ignore_value(mut self) -> Self {
185 self.0.ignore_value = true;
186 self
187 }
188
189 #[inline]
192 pub const fn with_ignore_lease(mut self) -> Self {
193 self.0.ignore_lease = true;
194 self
195 }
196}
197
198impl From<PutOptions> for PbPutRequest {
199 #[inline]
200 fn from(options: PutOptions) -> Self {
201 options.0
202 }
203}
204
205impl IntoRequest<PbPutRequest> for PutOptions {
206 #[inline]
207 fn into_request(self) -> Request<PbPutRequest> {
208 Request::new(self.into())
209 }
210}
211
212#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
214#[derive(Debug, Clone)]
215#[repr(transparent)]
216pub struct PutResponse(PbPutResponse);
217
218impl PutResponse {
219 #[inline]
221 const fn new(resp: PbPutResponse) -> Self {
222 Self(resp)
223 }
224
225 #[inline]
227 pub fn header(&self) -> Option<&ResponseHeader> {
228 self.0.header.as_ref().map(From::from)
229 }
230
231 #[inline]
233 pub fn take_header(&mut self) -> Option<ResponseHeader> {
234 self.0.header.take().map(ResponseHeader::new)
235 }
236
237 #[inline]
239 pub fn prev_key(&self) -> Option<&KeyValue> {
240 self.0.prev_kv.as_ref().map(From::from)
241 }
242
243 #[inline]
245 pub fn take_prev_key(&mut self) -> Option<KeyValue> {
246 self.0.prev_kv.take().map(KeyValue::new)
247 }
248
249 #[inline]
250 pub(crate) fn strip_prev_key_prefix(&mut self, prefix: &[u8]) {
251 if let Some(kv) = self.0.prev_kv.as_mut() {
252 kv.key.strip_key_prefix(prefix);
253 }
254 }
255}
256
257#[derive(Debug, Default, Clone)]
259pub struct GetOptions {
260 req: PbRangeRequest,
261 key_range: KeyRange,
262}
263
264impl GetOptions {
265 #[inline]
267 fn with_key(mut self, key: impl Into<Vec<u8>>) -> Self {
268 self.key_range.with_key(key);
269 self
270 }
271
272 #[inline]
274 pub const fn new() -> Self {
275 Self {
276 req: PbRangeRequest {
277 key: Vec::new(),
278 range_end: Vec::new(),
279 limit: 0,
280 revision: 0,
281 sort_order: 0,
282 sort_target: 0,
283 serializable: false,
284 keys_only: false,
285 count_only: false,
286 min_mod_revision: 0,
287 max_mod_revision: 0,
288 min_create_revision: 0,
289 max_create_revision: 0,
290 },
291 key_range: KeyRange::new(),
292 }
293 }
294
295 #[inline]
299 pub fn with_range(mut self, end_key: impl Into<Vec<u8>>) -> Self {
300 self.key_range.with_range(end_key);
301 self
302 }
303
304 #[inline]
306 pub fn with_from_key(mut self) -> Self {
307 self.key_range.with_from_key();
308 self
309 }
310
311 #[inline]
313 pub fn with_prefix(mut self) -> Self {
314 self.key_range.with_prefix();
315 self
316 }
317
318 #[inline]
320 pub fn with_all_keys(mut self) -> Self {
321 self.key_range.with_all_keys();
322 self
323 }
324
325 #[inline]
328 pub const fn with_limit(mut self, limit: i64) -> Self {
329 self.req.limit = limit;
330 self
331 }
332
333 #[inline]
337 pub const fn with_revision(mut self, revision: i64) -> Self {
338 self.req.revision = revision;
339 self
340 }
341
342 #[inline]
345 pub fn with_sort(mut self, target: SortTarget, order: SortOrder) -> Self {
346 if target == SortTarget::Key && order == SortOrder::Ascend {
347 self.req.sort_order = SortOrder::None as i32;
353 } else {
354 self.req.sort_order = order as i32;
355 }
356 self.req.sort_target = target as i32;
357 self
358 }
359
360 #[inline]
367 pub const fn with_serializable(mut self) -> Self {
368 self.req.serializable = true;
369 self
370 }
371
372 #[inline]
374 pub const fn with_keys_only(mut self) -> Self {
375 self.req.keys_only = true;
376 self
377 }
378
379 #[inline]
381 pub const fn with_count_only(mut self) -> Self {
382 self.req.count_only = true;
383 self
384 }
385
386 #[inline]
389 pub const fn with_min_mod_revision(mut self, revision: i64) -> Self {
390 self.req.min_mod_revision = revision;
391 self
392 }
393
394 #[inline]
397 pub const fn with_max_mod_revision(mut self, revision: i64) -> Self {
398 self.req.max_mod_revision = revision;
399 self
400 }
401
402 #[inline]
405 pub const fn with_min_create_revision(mut self, revision: i64) -> Self {
406 self.req.min_create_revision = revision;
407 self
408 }
409
410 #[inline]
413 pub const fn with_max_create_revision(mut self, revision: i64) -> Self {
414 self.req.max_create_revision = revision;
415 self
416 }
417
418 #[inline]
419 pub(crate) fn key_range_end_mut(&mut self) -> &mut Vec<u8> {
420 &mut self.key_range.range_end
421 }
422}
423
424impl From<GetOptions> for PbRangeRequest {
425 #[inline]
426 fn from(mut options: GetOptions) -> Self {
427 let (key, rang_end) = options.key_range.build();
428 options.req.key = key;
429 options.req.range_end = rang_end;
430 options.req
431 }
432}
433
434impl IntoRequest<PbRangeRequest> for GetOptions {
435 #[inline]
436 fn into_request(self) -> Request<PbRangeRequest> {
437 Request::new(self.into())
438 }
439}
440
441#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
443#[derive(Debug, Clone)]
444#[repr(transparent)]
445pub struct GetResponse(PbRangeResponse);
446
447impl GetResponse {
448 #[inline]
450 const fn new(resp: PbRangeResponse) -> Self {
451 Self(resp)
452 }
453
454 #[inline]
456 pub fn header(&self) -> Option<&ResponseHeader> {
457 self.0.header.as_ref().map(From::from)
458 }
459
460 #[inline]
462 pub fn take_header(&mut self) -> Option<ResponseHeader> {
463 self.0.header.take().map(ResponseHeader::new)
464 }
465
466 #[inline]
469 pub fn kvs(&self) -> &[KeyValue] {
470 unsafe { &*(self.0.kvs.as_slice() as *const _ as *const [KeyValue]) }
471 }
472
473 #[inline]
475 pub fn take_kvs(&mut self) -> Vec<KeyValue> {
476 let kvs = ManuallyDrop::new(std::mem::take(&mut self.0.kvs));
477 unsafe { Vec::from_raw_parts(kvs.as_ptr() as *mut KeyValue, kvs.len(), kvs.capacity()) }
478 }
479
480 #[inline]
481 pub(crate) fn strip_kvs_prefix(&mut self, prefix: &[u8]) {
482 for kv in self.0.kvs.iter_mut() {
483 kv.key.strip_key_prefix(prefix);
484 }
485 }
486
487 #[inline]
489 pub const fn more(&self) -> bool {
490 self.0.more
491 }
492
493 #[inline]
495 pub const fn count(&self) -> i64 {
496 self.0.count
497 }
498}
499
500#[derive(Debug, Default, Clone)]
502pub struct DeleteOptions {
503 req: PbDeleteRequest,
504 key_range: KeyRange,
505}
506
507impl DeleteOptions {
508 #[inline]
510 fn with_key(mut self, key: impl Into<Vec<u8>>) -> Self {
511 self.key_range.with_key(key);
512 self
513 }
514
515 #[inline]
517 pub const fn new() -> Self {
518 Self {
519 req: PbDeleteRequest {
520 key: Vec::new(),
521 range_end: Vec::new(),
522 prev_kv: false,
523 },
524 key_range: KeyRange::new(),
525 }
526 }
527
528 #[inline]
530 pub fn with_range(mut self, end_key: impl Into<Vec<u8>>) -> Self {
531 self.key_range.with_range(end_key);
532 self
533 }
534
535 #[inline]
537 pub fn with_from_key(mut self) -> Self {
538 self.key_range.with_from_key();
539 self
540 }
541
542 #[inline]
544 pub fn with_prefix(mut self) -> Self {
545 self.key_range.with_prefix();
546 self
547 }
548
549 #[inline]
551 pub fn with_all_keys(mut self) -> Self {
552 self.key_range.with_all_keys();
553 self
554 }
555
556 #[inline]
559 pub const fn with_prev_key(mut self) -> Self {
560 self.req.prev_kv = true;
561 self
562 }
563
564 #[inline]
565 pub(crate) fn key_range_end_mut(&mut self) -> &mut Vec<u8> {
566 &mut self.key_range.range_end
567 }
568}
569
570impl From<DeleteOptions> for PbDeleteRequest {
571 #[inline]
572 fn from(mut options: DeleteOptions) -> Self {
573 let (key, rang_end) = options.key_range.build();
574 options.req.key = key;
575 options.req.range_end = rang_end;
576 options.req
577 }
578}
579
580impl IntoRequest<PbDeleteRequest> for DeleteOptions {
581 #[inline]
582 fn into_request(self) -> Request<DeleteRangeRequest> {
583 Request::new(self.into())
584 }
585}
586
587#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
589#[derive(Debug, Clone)]
590#[repr(transparent)]
591pub struct DeleteResponse(PbDeleteResponse);
592
593impl DeleteResponse {
594 #[inline]
596 const fn new(resp: PbDeleteResponse) -> Self {
597 Self(resp)
598 }
599
600 #[inline]
602 pub fn header(&self) -> Option<&ResponseHeader> {
603 self.0.header.as_ref().map(From::from)
604 }
605
606 #[inline]
608 pub fn take_header(&mut self) -> Option<ResponseHeader> {
609 self.0.header.take().map(ResponseHeader::new)
610 }
611
612 #[inline]
614 pub const fn deleted(&self) -> i64 {
615 self.0.deleted
616 }
617
618 #[inline]
620 pub fn prev_kvs(&self) -> &[KeyValue] {
621 unsafe { &*(self.0.prev_kvs.as_slice() as *const _ as *const [KeyValue]) }
622 }
623
624 #[inline]
626 pub fn take_prev_kvs(&mut self) -> Vec<KeyValue> {
627 let kvs = ManuallyDrop::new(std::mem::take(&mut self.0.prev_kvs));
628 unsafe { Vec::from_raw_parts(kvs.as_ptr() as *mut KeyValue, kvs.len(), kvs.capacity()) }
629 }
630
631 #[inline]
632 pub(crate) fn strip_prev_kvs_prefix(&mut self, prefix: &[u8]) {
633 for kv in self.0.prev_kvs.iter_mut() {
634 kv.key.strip_key_prefix(prefix);
635 }
636 }
637}
638
639#[derive(Debug, Default, Clone)]
641#[repr(transparent)]
642pub struct CompactionOptions(PbCompactionRequest);
643
644impl CompactionOptions {
645 #[inline]
647 pub const fn new() -> Self {
648 Self(PbCompactionRequest {
649 revision: 0,
650 physical: false,
651 })
652 }
653
654 #[inline]
656 const fn with_revision(mut self, revision: i64) -> Self {
657 self.0.revision = revision;
658 self
659 }
660
661 #[inline]
665 pub const fn with_physical(mut self) -> Self {
666 self.0.physical = true;
667 self
668 }
669}
670
671impl IntoRequest<PbCompactionRequest> for CompactionOptions {
672 #[inline]
673 fn into_request(self) -> Request<CompactionRequest> {
674 Request::new(self.0)
675 }
676}
677
678#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
680#[derive(Debug, Clone)]
681#[repr(transparent)]
682pub struct CompactionResponse(PbCompactionResponse);
683
684impl CompactionResponse {
685 #[inline]
687 const fn new(resp: PbCompactionResponse) -> Self {
688 Self(resp)
689 }
690
691 #[inline]
693 pub fn header(&self) -> Option<&ResponseHeader> {
694 self.0.header.as_ref().map(From::from)
695 }
696
697 #[inline]
699 pub fn take_header(&mut self) -> Option<ResponseHeader> {
700 self.0.header.take().map(ResponseHeader::new)
701 }
702}
703
704#[derive(Debug, Clone)]
706#[repr(transparent)]
707pub struct Compare(PbCompare);
708
709impl Compare {
710 #[inline]
712 fn new(
713 key: impl Into<Vec<u8>>,
714 cmp: CompareOp,
715 target: CompareTarget,
716 target_union: TargetUnion,
717 ) -> Self {
718 Self(PbCompare {
719 result: cmp as i32,
720 target: target as i32,
721 key: key.into(),
722 range_end: Vec::new(),
723 target_union: Some(target_union),
724 })
725 }
726
727 #[inline]
729 pub fn version(key: impl Into<Vec<u8>>, cmp: CompareOp, version: i64) -> Self {
730 Self::new(
731 key,
732 cmp,
733 CompareTarget::Version,
734 TargetUnion::Version(version),
735 )
736 }
737
738 #[inline]
740 pub fn create_revision(key: impl Into<Vec<u8>>, cmp: CompareOp, revision: i64) -> Self {
741 Self::new(
742 key,
743 cmp,
744 CompareTarget::Create,
745 TargetUnion::CreateRevision(revision),
746 )
747 }
748
749 #[inline]
751 pub fn mod_revision(key: impl Into<Vec<u8>>, cmp: CompareOp, revision: i64) -> Self {
752 Self::new(
753 key,
754 cmp,
755 CompareTarget::Mod,
756 TargetUnion::ModRevision(revision),
757 )
758 }
759
760 #[inline]
762 pub fn value(key: impl Into<Vec<u8>>, cmp: CompareOp, value: impl Into<Vec<u8>>) -> Self {
763 Self::new(
764 key,
765 cmp,
766 CompareTarget::Value,
767 TargetUnion::Value(value.into()),
768 )
769 }
770
771 #[inline]
773 pub fn lease(key: impl Into<Vec<u8>>, cmp: CompareOp, lease: i64) -> Self {
774 Self::new(key, cmp, CompareTarget::Lease, TargetUnion::Lease(lease))
775 }
776
777 #[inline]
779 pub fn with_range(mut self, end: impl Into<Vec<u8>>) -> Self {
780 self.0.range_end = end.into();
781 self
782 }
783
784 #[inline]
786 pub fn with_prefix(mut self) -> Self {
787 self.0.range_end = get_prefix(&self.0.key);
788 self
789 }
790}
791
792#[derive(Debug, Clone)]
794#[repr(transparent)]
795pub struct TxnOp(PbTxnOp);
796
797impl TxnOp {
798 #[inline]
800 pub fn put(
801 key: impl Into<Vec<u8>>,
802 value: impl Into<Vec<u8>>,
803 options: Option<PutOptions>,
804 ) -> Self {
805 TxnOp(PbTxnOp::RequestPut(
806 options.unwrap_or_default().with_kv(key, value).into(),
807 ))
808 }
809
810 #[inline]
812 pub fn get(key: impl Into<Vec<u8>>, options: Option<GetOptions>) -> Self {
813 TxnOp(PbTxnOp::RequestRange(
814 options.unwrap_or_default().with_key(key).into(),
815 ))
816 }
817
818 #[inline]
820 pub fn delete(key: impl Into<Vec<u8>>, options: Option<DeleteOptions>) -> Self {
821 TxnOp(PbTxnOp::RequestDeleteRange(
822 options.unwrap_or_default().with_key(key).into(),
823 ))
824 }
825
826 #[inline]
828 pub fn txn(txn: Txn) -> Self {
829 TxnOp(PbTxnOp::RequestTxn(txn.into()))
830 }
831}
832
833impl From<TxnOp> for PbTxnOp {
834 #[inline]
835 fn from(op: TxnOp) -> Self {
836 op.0
837 }
838}
839
840#[derive(Debug, Default, Clone)]
842pub struct Txn {
843 req: PbTxnRequest,
844 c_when: bool,
845 c_then: bool,
846 c_else: bool,
847}
848
849impl Txn {
850 #[inline]
852 pub const fn new() -> Self {
853 Self {
854 req: PbTxnRequest {
855 compare: Vec::new(),
856 success: Vec::new(),
857 failure: Vec::new(),
858 },
859 c_when: false,
860 c_then: false,
861 c_else: false,
862 }
863 }
864
865 #[inline]
869 pub fn when(mut self, compares: impl Into<Vec<Compare>>) -> Self {
870 assert!(!self.c_when, "cannot call when twice");
871 assert!(!self.c_then, "cannot call when after and_then");
872 assert!(!self.c_else, "cannot call when after or_else");
873
874 self.c_when = true;
875
876 let compares = ManuallyDrop::new(compares.into());
877 self.req.compare = unsafe {
878 Vec::from_raw_parts(
879 compares.as_ptr() as *mut PbCompare,
880 compares.len(),
881 compares.capacity(),
882 )
883 };
884
885 self
886 }
887
888 #[inline]
891 pub fn and_then(mut self, operations: impl Into<Vec<TxnOp>>) -> Self {
892 assert!(!self.c_then, "cannot call and_then twice");
893 assert!(!self.c_else, "cannot call and_then after or_else");
894
895 self.c_then = true;
896 self.req.success = operations
897 .into()
898 .into_iter()
899 .map(|op| PbTxnRequestOp {
900 request: Some(op.into()),
901 })
902 .collect();
903 self
904 }
905
906 #[inline]
909 pub fn or_else(mut self, operations: impl Into<Vec<TxnOp>>) -> Self {
910 assert!(!self.c_else, "cannot call or_else twice");
911
912 self.c_else = true;
913 self.req.failure = operations
914 .into()
915 .into_iter()
916 .map(|op| PbTxnRequestOp {
917 request: Some(op.into()),
918 })
919 .collect();
920 self
921 }
922
923 #[inline]
924 pub(crate) fn prefix_with(&mut self, prefix: &[u8]) {
925 self.req.prefix_with(prefix);
926 }
927}
928
929impl PbTxnRequest {
930 fn prefix_with(&mut self, prefix: &[u8]) {
931 let prefix_op = |op: &mut PbTxnRequestOp| {
932 if let Some(request) = &mut op.request {
933 match request {
934 PbTxnOp::RequestRange(req) => {
935 req.key.prefix_with(prefix);
936 req.range_end.prefix_range_end_with(prefix);
937 }
938 PbTxnOp::RequestPut(req) => {
939 req.key.prefix_with(prefix);
940 }
941 PbTxnOp::RequestDeleteRange(req) => {
942 req.key.prefix_with(prefix);
943 req.range_end.prefix_range_end_with(prefix);
944 }
945 PbTxnOp::RequestTxn(req) => {
946 req.prefix_with(prefix);
947 }
948 }
949 }
950 };
951
952 self.compare.iter_mut().for_each(|cmp| {
953 cmp.key.prefix_with(prefix);
954 cmp.range_end.prefix_range_end_with(prefix);
955 });
956 self.success.iter_mut().for_each(prefix_op);
957 self.failure.iter_mut().for_each(prefix_op);
958 }
959}
960
961impl From<Txn> for PbTxnRequest {
962 #[inline]
963 fn from(txn: Txn) -> Self {
964 txn.req
965 }
966}
967
968impl IntoRequest<PbTxnRequest> for Txn {
969 #[inline]
970 fn into_request(self) -> Request<PbTxnRequest> {
971 Request::new(self.into())
972 }
973}
974
975#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
977#[derive(Debug, Clone)]
978pub enum TxnOpResponse {
979 Put(PutResponse),
980 Get(GetResponse),
981 Delete(DeleteResponse),
982 Txn(TxnResponse),
983}
984
985#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
987#[derive(Debug, Clone)]
988#[repr(transparent)]
989pub struct TxnResponse(PbTxnResponse);
990
991impl TxnResponse {
992 #[inline]
994 const fn new(resp: PbTxnResponse) -> Self {
995 Self(resp)
996 }
997
998 #[inline]
1000 pub fn header(&self) -> Option<&ResponseHeader> {
1001 self.0.header.as_ref().map(From::from)
1002 }
1003
1004 #[inline]
1006 pub fn take_header(&mut self) -> Option<ResponseHeader> {
1007 self.0.header.take().map(ResponseHeader::new)
1008 }
1009
1010 #[inline]
1012 pub const fn succeeded(&self) -> bool {
1013 self.0.succeeded
1014 }
1015
1016 #[inline]
1018 pub fn op_responses(&self) -> Vec<TxnOpResponse> {
1019 self.0
1020 .responses
1021 .iter()
1022 .map(|resp| match resp.response.as_ref().unwrap() {
1023 PbTxnOpResponse::ResponsePut(put) => {
1024 TxnOpResponse::Put(PutResponse::new(put.clone()))
1025 }
1026 PbTxnOpResponse::ResponseRange(get) => {
1027 TxnOpResponse::Get(GetResponse::new(get.clone()))
1028 }
1029 PbTxnOpResponse::ResponseDeleteRange(delete) => {
1030 TxnOpResponse::Delete(DeleteResponse::new(delete.clone()))
1031 }
1032 PbTxnOpResponse::ResponseTxn(txn) => {
1033 TxnOpResponse::Txn(TxnResponse::new(txn.clone()))
1034 }
1035 })
1036 .collect()
1037 }
1038
1039 #[inline]
1040 pub(crate) fn strip_key_prefix(&mut self, prefix: &[u8]) {
1041 self.0.strip_key_prefix(prefix);
1042 }
1043}
1044
1045impl PbTxnResponse {
1046 fn strip_key_prefix(&mut self, prefix: &[u8]) {
1047 self.responses.iter_mut().for_each(|op| {
1048 if let Some(resp) = &mut op.response {
1049 match resp {
1050 PbTxnOpResponse::ResponseRange(r) => {
1051 for kv in r.kvs.iter_mut() {
1052 kv.key.strip_key_prefix(prefix);
1053 }
1054 }
1055 PbTxnOpResponse::ResponsePut(r) => {
1056 if let Some(kv) = r.prev_kv.as_mut() {
1057 kv.key.strip_key_prefix(prefix);
1058 }
1059 }
1060 PbTxnOpResponse::ResponseDeleteRange(r) => {
1061 for kv in r.prev_kvs.iter_mut() {
1062 kv.key.strip_key_prefix(prefix);
1063 }
1064 }
1065 PbTxnOpResponse::ResponseTxn(r) => {
1066 r.strip_key_prefix(prefix);
1067 }
1068 }
1069 }
1070 });
1071 }
1072}