1use super::{
2 DeleteRequest, DeleteResponse, KeyRange, PutRequest, PutResponse, RangeRequest, RangeResponse,
3};
4use crate::proto::etcdserverpb;
5use crate::ResponseHeader;
6use etcdserverpb::compare::{CompareResult, CompareTarget, TargetUnion};
7use etcdserverpb::Compare;
8
9#[derive(Debug)]
10pub struct TxnRequest {
11 proto: etcdserverpb::TxnRequest,
12}
13
14impl TxnRequest {
15 pub fn new() -> Self {
16 Self {
17 proto: etcdserverpb::TxnRequest {
18 compare: vec![],
19 success: vec![],
20 failure: vec![],
21 },
22 }
23 }
24
25 pub fn when_version(mut self, key_range: KeyRange, cmp: TxnCmp, version: usize) -> Self {
26 let result: CompareResult = cmp.into();
27 self.proto.compare.push(Compare {
28 result: result as i32,
29 target: CompareTarget::Version as i32,
30 key: key_range.key,
31 range_end: key_range.range_end,
32 target_union: Some(TargetUnion::Version(version as i64)),
33 });
34 self
35 }
36
37 pub fn when_create_revision(
38 mut self,
39 key_range: KeyRange,
40 cmp: TxnCmp,
41 revision: usize,
42 ) -> Self {
43 let result: CompareResult = cmp.into();
44 self.proto.compare.push(Compare {
45 result: result as i32,
46 target: CompareTarget::Create as i32,
47 key: key_range.key,
48 range_end: key_range.range_end,
49 target_union: Some(TargetUnion::CreateRevision(revision as i64)),
50 });
51 self
52 }
53
54 pub fn when_mod_revision(mut self, key_range: KeyRange, cmp: TxnCmp, revision: usize) -> Self {
55 let result: CompareResult = cmp.into();
56 self.proto.compare.push(Compare {
57 result: result as i32,
58 target: CompareTarget::Mod as i32,
59 key: key_range.key,
60 range_end: key_range.range_end,
61 target_union: Some(TargetUnion::ModRevision(revision as i64)),
62 });
63 self
64 }
65
66 pub fn when_value<V>(mut self, key_range: KeyRange, cmp: TxnCmp, value: V) -> Self
67 where
68 V: Into<Vec<u8>>,
69 {
70 let result: CompareResult = cmp.into();
71 self.proto.compare.push(Compare {
72 result: result as i32,
73 target: CompareTarget::Value as i32,
74 key: key_range.key,
75 range_end: key_range.range_end,
76 target_union: Some(TargetUnion::Value(value.into())),
77 });
78 self
79 }
80
81 pub fn and_then<O>(mut self, op: O) -> Self
82 where
83 O: Into<TxnOp>,
84 {
85 self.proto.success.push(op.into().into());
86 self
87 }
88
89 pub fn or_else<O>(mut self, op: O) -> Self
90 where
91 O: Into<TxnOp>,
92 {
93 self.proto.failure.push(op.into().into());
94 self
95 }
96}
97
98impl Default for TxnRequest {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl From<TxnRequest> for crate::proto::etcdserverpb::TxnRequest {
105 fn from(x: TxnRequest) -> Self {
106 x.proto
107 }
108}
109
110pub enum TxnOp {
111 Range(RangeRequest),
112 Put(PutRequest),
113 Delete(DeleteRequest),
114 Txn(TxnRequest),
115}
116
117impl From<TxnOp> for etcdserverpb::RequestOp {
118 fn from(x: TxnOp) -> etcdserverpb::RequestOp {
119 use etcdserverpb::request_op::Request;
120
121 let req = match x {
122 TxnOp::Range(req) => Request::RequestRange(req.into()),
123 TxnOp::Put(req) => Request::RequestPut(req.into()),
124 TxnOp::Delete(req) => Request::RequestDeleteRange(req.into()),
125 TxnOp::Txn(req) => Request::RequestTxn(req.into()),
126 };
127
128 etcdserverpb::RequestOp { request: Some(req) }
129 }
130}
131
132impl From<RangeRequest> for TxnOp {
133 fn from(req: RangeRequest) -> Self {
134 Self::Range(req)
135 }
136}
137
138impl From<PutRequest> for TxnOp {
139 fn from(req: PutRequest) -> Self {
140 Self::Put(req)
141 }
142}
143
144impl From<DeleteRequest> for TxnOp {
145 fn from(req: DeleteRequest) -> Self {
146 Self::Delete(req)
147 }
148}
149
150impl From<TxnRequest> for TxnOp {
151 fn from(req: TxnRequest) -> Self {
152 Self::Txn(req)
153 }
154}
155
156pub enum TxnCmp {
157 Equal,
158 NotEqual,
159 Greater,
160 Less,
161}
162
163impl From<TxnCmp> for CompareResult {
164 fn from(x: TxnCmp) -> CompareResult {
165 match x {
166 TxnCmp::Equal => CompareResult::Equal,
167 TxnCmp::NotEqual => CompareResult::NotEqual,
168 TxnCmp::Greater => CompareResult::Greater,
169 TxnCmp::Less => CompareResult::Less,
170 }
171 }
172}
173
174#[derive(Debug, Clone)]
175pub enum TxnOpResponse {
176 Range(RangeResponse),
177 Put(PutResponse),
178 Delete(DeleteResponse),
179 Txn(TxnResponse),
180}
181
182impl From<etcdserverpb::ResponseOp> for TxnOpResponse {
183 fn from(mut resp: etcdserverpb::ResponseOp) -> Self {
184 use etcdserverpb::response_op::Response;
185 match resp.response.take().unwrap() {
186 Response::ResponseRange(r) => Self::Range(From::from(r)),
187 Response::ResponsePut(r) => Self::Put(From::from(r)),
188 Response::ResponseTxn(r) => Self::Txn(From::from(r)),
189 Response::ResponseDeleteRange(r) => Self::Delete(From::from(r)),
190 }
191 }
192}
193
194#[derive(Debug, Clone)]
195pub struct TxnResponse {
196 pub header: ResponseHeader,
197 pub succeeded: bool,
198 pub responses: Vec<TxnOpResponse>,
199}
200
201impl From<etcdserverpb::TxnResponse> for TxnResponse {
202 fn from(proto: etcdserverpb::TxnResponse) -> Self {
203 Self {
204 header: From::from(proto.header.expect("must fetch header")),
205 succeeded: proto.succeeded,
206 responses: proto.responses.into_iter().map(From::from).collect(),
207 }
208 }
209}