1use anyhow::{Result, bail};
2use vbare::OwnedVersionedData;
3
4use crate::generated::{v1, v2, v3, v4};
5
6pub enum ToClient {
7 V1(v1::ToClient),
8 V2(v2::ToClient),
9 V3(v3::ToClient),
10 V4(v4::ToClient),
11}
12
13impl OwnedVersionedData for ToClient {
14 type Latest = v4::ToClient;
15
16 fn wrap_latest(latest: Self::Latest) -> Self {
17 Self::V4(latest)
18 }
19
20 fn unwrap_latest(self) -> Result<Self::Latest> {
21 match self {
22 Self::V4(data) => Ok(data),
23 _ => bail!("version not latest"),
24 }
25 }
26
27 fn deserialize_version(payload: &[u8], version: u16) -> Result<Self> {
28 match version {
29 1 => Ok(Self::V1(serde_bare::from_slice(payload)?)),
30 2 => Ok(Self::V2(serde_bare::from_slice(payload)?)),
31 3 => Ok(Self::V3(serde_bare::from_slice(payload)?)),
32 4 => Ok(Self::V4(serde_bare::from_slice(payload)?)),
33 _ => bail!("invalid client protocol version: {version}"),
34 }
35 }
36
37 fn serialize_version(self, version: u16) -> Result<Vec<u8>> {
38 match (self, version) {
39 (Self::V1(data), 1) => serde_bare::to_vec(&data).map_err(Into::into),
40 (Self::V2(data), 2) => serde_bare::to_vec(&data).map_err(Into::into),
41 (Self::V3(data), 3) => serde_bare::to_vec(&data).map_err(Into::into),
42 (Self::V4(data), 4) => serde_bare::to_vec(&data).map_err(Into::into),
43 (_, version) => bail!("unexpected client protocol version: {version}"),
44 }
45 }
46
47 fn deserialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
48 vec![Self::v1_to_v2, Self::v2_to_v3, Self::v3_to_v4]
49 }
50
51 fn serialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
52 vec![Self::v4_to_v3, Self::v3_to_v2, Self::v2_to_v1]
53 }
54}
55
56impl ToClient {
57 fn v1_to_v2(self) -> Result<Self> {
58 let Self::V1(data) = self else {
59 bail!("expected client protocol v1 ToClient")
60 };
61
62 let body = match data.body {
63 v1::ToClientBody::Init(init) => v2::ToClientBody::Init(v2::Init {
64 actor_id: init.actor_id,
65 connection_id: init.connection_id,
66 }),
67 v1::ToClientBody::Error(error) => v2::ToClientBody::Error(v2::Error {
68 group: error.group,
69 code: error.code,
70 message: error.message,
71 metadata: error.metadata,
72 action_id: error.action_id,
73 }),
74 v1::ToClientBody::ActionResponse(response) => {
75 v2::ToClientBody::ActionResponse(v2::ActionResponse {
76 id: response.id,
77 output: response.output,
78 })
79 }
80 v1::ToClientBody::Event(event) => v2::ToClientBody::Event(v2::Event {
81 name: event.name,
82 args: event.args,
83 }),
84 };
85
86 Ok(Self::V2(v2::ToClient { body }))
87 }
88
89 fn v2_to_v3(self) -> Result<Self> {
90 let Self::V2(data) = self else {
91 bail!("expected client protocol v2 ToClient")
92 };
93 Ok(Self::V3(data.into()))
94 }
95
96 fn v3_to_v4(self) -> Result<Self> {
97 let Self::V3(data) = self else {
98 bail!("expected client protocol v3 ToClient")
99 };
100
101 let body = match data.body {
102 v3::ToClientBody::Init(init) => v4::ToClientBody::Init(v4::Init {
103 actor_id: init.actor_id,
104 connection_id: init.connection_id,
105 }),
106 v3::ToClientBody::Error(error) => v4::ToClientBody::Error(v4::Error {
107 group: error.group,
108 code: error.code,
109 message: error.message,
110 metadata: error.metadata,
111 action_id: error.action_id,
112 actor: None,
113 }),
114 v3::ToClientBody::ActionResponse(response) => {
115 v4::ToClientBody::ActionResponse(v4::ActionResponse {
116 id: response.id,
117 output: response.output,
118 })
119 }
120 v3::ToClientBody::Event(event) => v4::ToClientBody::Event(v4::Event {
121 name: event.name,
122 args: event.args,
123 }),
124 };
125
126 Ok(Self::V4(v4::ToClient { body }))
127 }
128
129 fn v4_to_v3(self) -> Result<Self> {
130 let Self::V4(data) = self else {
131 bail!("expected client protocol v4 ToClient")
132 };
133
134 let body = match data.body {
135 v4::ToClientBody::Init(init) => v3::ToClientBody::Init(v3::Init {
136 actor_id: init.actor_id,
137 connection_id: init.connection_id,
138 }),
139 v4::ToClientBody::Error(error) => v3::ToClientBody::Error(v3::Error {
140 group: error.group,
141 code: error.code,
142 message: error.message,
143 metadata: error.metadata,
144 action_id: error.action_id,
145 }),
146 v4::ToClientBody::ActionResponse(response) => {
147 v3::ToClientBody::ActionResponse(v3::ActionResponse {
148 id: response.id,
149 output: response.output,
150 })
151 }
152 v4::ToClientBody::Event(event) => v3::ToClientBody::Event(v3::Event {
153 name: event.name,
154 args: event.args,
155 }),
156 };
157
158 Ok(Self::V3(v3::ToClient { body }))
159 }
160
161 fn v3_to_v2(self) -> Result<Self> {
162 let Self::V3(data) = self else {
163 bail!("expected client protocol v3 ToClient")
164 };
165 Ok(Self::V2(data.into()))
166 }
167
168 fn v2_to_v1(self) -> Result<Self> {
169 let Self::V2(data) = self else {
170 bail!("expected client protocol v2 ToClient")
171 };
172
173 let body = match data.body {
174 v2::ToClientBody::Init(init) => v1::ToClientBody::Init(v1::Init {
175 actor_id: init.actor_id,
176 connection_id: init.connection_id,
177 connection_token: String::new(),
178 }),
179 v2::ToClientBody::Error(error) => v1::ToClientBody::Error(v1::Error {
180 group: error.group,
181 code: error.code,
182 message: error.message,
183 metadata: error.metadata,
184 action_id: error.action_id,
185 }),
186 v2::ToClientBody::ActionResponse(response) => {
187 v1::ToClientBody::ActionResponse(v1::ActionResponse {
188 id: response.id,
189 output: response.output,
190 })
191 }
192 v2::ToClientBody::Event(event) => v1::ToClientBody::Event(v1::Event {
193 name: event.name,
194 args: event.args,
195 }),
196 };
197
198 Ok(Self::V1(v1::ToClient { body }))
199 }
200}
201
202macro_rules! impl_same_fields_pair {
203 ($left:ident, $right:ident, $ty:ident { $($field:ident),+ $(,)? }) => {
204 impl From<$left::$ty> for $right::$ty {
205 fn from(value: $left::$ty) -> Self {
206 Self {
207 $($field: value.$field),+
208 }
209 }
210 }
211
212 impl From<$right::$ty> for $left::$ty {
213 fn from(value: $right::$ty) -> Self {
214 Self {
215 $($field: value.$field),+
216 }
217 }
218 }
219 };
220}
221
222macro_rules! impl_to_server_pair {
223 ($left:ident, $right:ident) => {
224 impl From<$left::ToServerBody> for $right::ToServerBody {
225 fn from(value: $left::ToServerBody) -> Self {
226 match value {
227 $left::ToServerBody::ActionRequest(request) => {
228 Self::ActionRequest(request.into())
229 }
230 $left::ToServerBody::SubscriptionRequest(request) => {
231 Self::SubscriptionRequest(request.into())
232 }
233 }
234 }
235 }
236
237 impl From<$right::ToServerBody> for $left::ToServerBody {
238 fn from(value: $right::ToServerBody) -> Self {
239 match value {
240 $right::ToServerBody::ActionRequest(request) => {
241 Self::ActionRequest(request.into())
242 }
243 $right::ToServerBody::SubscriptionRequest(request) => {
244 Self::SubscriptionRequest(request.into())
245 }
246 }
247 }
248 }
249
250 impl From<$left::ToServer> for $right::ToServer {
251 fn from(value: $left::ToServer) -> Self {
252 Self {
253 body: value.body.into(),
254 }
255 }
256 }
257
258 impl From<$right::ToServer> for $left::ToServer {
259 fn from(value: $right::ToServer) -> Self {
260 Self {
261 body: value.body.into(),
262 }
263 }
264 }
265 };
266}
267
268macro_rules! impl_common_pair {
269 ($left:ident, $right:ident) => {
270 impl_same_fields_pair!($left, $right, ActionRequest { id, name, args });
271 impl_same_fields_pair!(
272 $left,
273 $right,
274 SubscriptionRequest {
275 event_name,
276 subscribe,
277 }
278 );
279 impl_to_server_pair!($left, $right);
280 impl_same_fields_pair!($left, $right, HttpActionRequest { args });
281 impl_same_fields_pair!($left, $right, HttpActionResponse { output });
282 impl_same_fields_pair!($left, $right, HttpResolveResponse { actor_id });
283 };
284}
285
286macro_rules! impl_to_client_v2_v3_pair {
287 () => {
288 impl_same_fields_pair!(
289 v2,
290 v3,
291 Init {
292 actor_id,
293 connection_id,
294 }
295 );
296 impl_same_fields_pair!(
297 v2,
298 v3,
299 Error {
300 group,
301 code,
302 message,
303 metadata,
304 action_id,
305 }
306 );
307 impl_same_fields_pair!(v2, v3, ActionResponse { id, output });
308 impl_same_fields_pair!(v2, v3, Event { name, args });
309
310 impl From<v2::ToClientBody> for v3::ToClientBody {
311 fn from(value: v2::ToClientBody) -> Self {
312 match value {
313 v2::ToClientBody::Init(init) => Self::Init(init.into()),
314 v2::ToClientBody::Error(error) => Self::Error(error.into()),
315 v2::ToClientBody::ActionResponse(response) => {
316 Self::ActionResponse(response.into())
317 }
318 v2::ToClientBody::Event(event) => Self::Event(event.into()),
319 }
320 }
321 }
322
323 impl From<v3::ToClientBody> for v2::ToClientBody {
324 fn from(value: v3::ToClientBody) -> Self {
325 match value {
326 v3::ToClientBody::Init(init) => Self::Init(init.into()),
327 v3::ToClientBody::Error(error) => Self::Error(error.into()),
328 v3::ToClientBody::ActionResponse(response) => {
329 Self::ActionResponse(response.into())
330 }
331 v3::ToClientBody::Event(event) => Self::Event(event.into()),
332 }
333 }
334 }
335
336 impl From<v2::ToClient> for v3::ToClient {
337 fn from(value: v2::ToClient) -> Self {
338 Self {
339 body: value.body.into(),
340 }
341 }
342 }
343
344 impl From<v3::ToClient> for v2::ToClient {
345 fn from(value: v3::ToClient) -> Self {
346 Self {
347 body: value.body.into(),
348 }
349 }
350 }
351 };
352}
353
354impl_common_pair!(v1, v2);
355impl_common_pair!(v2, v3);
356impl_common_pair!(v3, v4);
357impl_to_client_v2_v3_pair!();
358impl_same_fields_pair!(
359 v1,
360 v2,
361 HttpResponseError {
362 group,
363 code,
364 message,
365 metadata,
366 }
367);
368impl_same_fields_pair!(
369 v2,
370 v3,
371 HttpResponseError {
372 group,
373 code,
374 message,
375 metadata,
376 }
377);
378impl_same_fields_pair!(
379 v3,
380 v4,
381 HttpQueueSendRequest {
382 body,
383 name,
384 wait,
385 timeout,
386 }
387);
388impl_same_fields_pair!(v3, v4, HttpQueueSendResponse { status, response });
389
390macro_rules! impl_versioned_manual {
391 ($name:ident, $latest_ty:path, $v1_ty:path, $v2_ty:path, $v3_ty:path, $v4_ty:path) => {
392 pub enum $name {
393 V1($v1_ty),
394 V2($v2_ty),
395 V3($v3_ty),
396 V4($v4_ty),
397 }
398
399 impl OwnedVersionedData for $name {
400 type Latest = $latest_ty;
401
402 fn wrap_latest(latest: Self::Latest) -> Self {
403 Self::V4(latest)
404 }
405
406 fn unwrap_latest(self) -> Result<Self::Latest> {
407 match self {
408 Self::V4(data) => Ok(data),
409 _ => bail!("version not latest"),
410 }
411 }
412
413 fn deserialize_version(payload: &[u8], version: u16) -> Result<Self> {
414 match version {
415 1 => Ok(Self::V1(serde_bare::from_slice(payload)?)),
416 2 => Ok(Self::V2(serde_bare::from_slice(payload)?)),
417 3 => Ok(Self::V3(serde_bare::from_slice(payload)?)),
418 4 => Ok(Self::V4(serde_bare::from_slice(payload)?)),
419 _ => bail!(
420 "invalid client protocol version for {}: {version}",
421 stringify!($name)
422 ),
423 }
424 }
425
426 fn serialize_version(self, version: u16) -> Result<Vec<u8>> {
427 match (self, version) {
428 (Self::V1(data), 1) => serde_bare::to_vec(&data).map_err(Into::into),
429 (Self::V2(data), 2) => serde_bare::to_vec(&data).map_err(Into::into),
430 (Self::V3(data), 3) => serde_bare::to_vec(&data).map_err(Into::into),
431 (Self::V4(data), 4) => serde_bare::to_vec(&data).map_err(Into::into),
432 (_, version) => bail!(
433 "unexpected client protocol version for {}: {version}",
434 stringify!($name)
435 ),
436 }
437 }
438
439 fn deserialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
440 vec![Self::v1_to_v2, Self::v2_to_v3, Self::v3_to_v4]
441 }
442
443 fn serialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
444 vec![Self::v4_to_v3, Self::v3_to_v2, Self::v2_to_v1]
445 }
446 }
447
448 impl $name {
449 fn v1_to_v2(self) -> Result<Self> {
450 let Self::V1(data) = self else {
451 bail!("expected client protocol v1 {}", stringify!($name))
452 };
453 Ok(Self::V2(data.into()))
454 }
455
456 fn v2_to_v3(self) -> Result<Self> {
457 let Self::V2(data) = self else {
458 bail!("expected client protocol v2 {}", stringify!($name))
459 };
460 Ok(Self::V3(data.into()))
461 }
462
463 fn v3_to_v4(self) -> Result<Self> {
464 let Self::V3(data) = self else {
465 bail!("expected client protocol v3 {}", stringify!($name))
466 };
467 Ok(Self::V4(data.into()))
468 }
469
470 fn v4_to_v3(self) -> Result<Self> {
471 let Self::V4(data) = self else {
472 bail!("expected client protocol v4 {}", stringify!($name))
473 };
474 Ok(Self::V3(data.into()))
475 }
476
477 fn v3_to_v2(self) -> Result<Self> {
478 let Self::V3(data) = self else {
479 bail!("expected client protocol v3 {}", stringify!($name))
480 };
481 Ok(Self::V2(data.into()))
482 }
483
484 fn v2_to_v1(self) -> Result<Self> {
485 let Self::V2(data) = self else {
486 bail!("expected client protocol v2 {}", stringify!($name))
487 };
488 Ok(Self::V1(data.into()))
489 }
490 }
491 };
492}
493
494macro_rules! impl_versioned_v3_only {
495 ($name:ident, $latest_ty:path) => {
496 pub enum $name {
497 V3(v3::$name),
498 V4($latest_ty),
499 }
500
501 impl OwnedVersionedData for $name {
502 type Latest = $latest_ty;
503
504 fn wrap_latest(latest: Self::Latest) -> Self {
505 Self::V4(latest)
506 }
507
508 fn unwrap_latest(self) -> Result<Self::Latest> {
509 match self {
510 Self::V4(data) => Ok(data),
511 _ => bail!("version not latest"),
512 }
513 }
514
515 fn deserialize_version(payload: &[u8], version: u16) -> Result<Self> {
516 match version {
517 3 => Ok(Self::V3(serde_bare::from_slice(payload)?)),
518 4 => Ok(Self::V4(serde_bare::from_slice(payload)?)),
519 _ => bail!(
520 "{} only exists in client protocol v3, got {version}",
521 stringify!($name)
522 ),
523 }
524 }
525
526 fn serialize_version(self, version: u16) -> Result<Vec<u8>> {
527 match (self, version) {
528 (Self::V3(data), 3) => serde_bare::to_vec(&data).map_err(Into::into),
529 (Self::V4(data), 4) => serde_bare::to_vec(&data).map_err(Into::into),
530 (_, version) => bail!(
531 "{} only exists in client protocol v3, got {version}",
532 stringify!($name)
533 ),
534 }
535 }
536
537 fn deserialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
538 vec![Ok, Ok, Self::v3_to_v4]
539 }
540
541 fn serialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
542 vec![Self::v4_to_v3, Ok, Ok]
543 }
544 }
545
546 impl $name {
547 fn v3_to_v4(self) -> Result<Self> {
548 let Self::V3(data) = self else {
549 bail!("expected client protocol v3 {}", stringify!($name))
550 };
551 Ok(Self::V4(data.into()))
552 }
553
554 fn v4_to_v3(self) -> Result<Self> {
555 let Self::V4(data) = self else {
556 bail!("expected client protocol v4 {}", stringify!($name))
557 };
558 Ok(Self::V3(data.into()))
559 }
560 }
561 };
562}
563
564impl_versioned_manual!(
565 ToServer,
566 v4::ToServer,
567 v1::ToServer,
568 v2::ToServer,
569 v3::ToServer,
570 v4::ToServer
571);
572impl_versioned_manual!(
573 HttpActionRequest,
574 v4::HttpActionRequest,
575 v1::HttpActionRequest,
576 v2::HttpActionRequest,
577 v3::HttpActionRequest,
578 v4::HttpActionRequest
579);
580impl_versioned_manual!(
581 HttpActionResponse,
582 v4::HttpActionResponse,
583 v1::HttpActionResponse,
584 v2::HttpActionResponse,
585 v3::HttpActionResponse,
586 v4::HttpActionResponse
587);
588impl_versioned_manual!(
589 HttpResolveResponse,
590 v4::HttpResolveResponse,
591 v1::HttpResolveResponse,
592 v2::HttpResolveResponse,
593 v3::HttpResolveResponse,
594 v4::HttpResolveResponse
595);
596impl_versioned_v3_only!(HttpQueueSendRequest, v4::HttpQueueSendRequest);
597impl_versioned_v3_only!(HttpQueueSendResponse, v4::HttpQueueSendResponse);
598
599pub enum HttpResponseError {
600 V1(v1::HttpResponseError),
601 V2(v2::HttpResponseError),
602 V3(v3::HttpResponseError),
603 V4(v4::HttpResponseError),
604}
605
606impl OwnedVersionedData for HttpResponseError {
607 type Latest = v4::HttpResponseError;
608
609 fn wrap_latest(latest: Self::Latest) -> Self {
610 Self::V4(latest)
611 }
612
613 fn unwrap_latest(self) -> Result<Self::Latest> {
614 match self {
615 Self::V4(data) => Ok(data),
616 _ => bail!("version not latest"),
617 }
618 }
619
620 fn deserialize_version(payload: &[u8], version: u16) -> Result<Self> {
621 match version {
622 1 => Ok(Self::V1(serde_bare::from_slice(payload)?)),
623 2 => Ok(Self::V2(serde_bare::from_slice(payload)?)),
624 3 => Ok(Self::V3(serde_bare::from_slice(payload)?)),
625 4 => Ok(Self::V4(serde_bare::from_slice(payload)?)),
626 _ => bail!("invalid client protocol version for HttpResponseError: {version}"),
627 }
628 }
629
630 fn serialize_version(self, version: u16) -> Result<Vec<u8>> {
631 match (self, version) {
632 (Self::V1(data), 1) => serde_bare::to_vec(&data).map_err(Into::into),
633 (Self::V2(data), 2) => serde_bare::to_vec(&data).map_err(Into::into),
634 (Self::V3(data), 3) => serde_bare::to_vec(&data).map_err(Into::into),
635 (Self::V4(data), 4) => serde_bare::to_vec(&data).map_err(Into::into),
636 (_, version) => {
637 bail!("unexpected client protocol version for HttpResponseError: {version}")
638 }
639 }
640 }
641
642 fn deserialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
643 vec![Self::v1_to_v2, Self::v2_to_v3, Self::v3_to_v4]
644 }
645
646 fn serialize_converters() -> Vec<impl Fn(Self) -> Result<Self>> {
647 vec![Self::v4_to_v3, Self::v3_to_v2, Self::v2_to_v1]
648 }
649}
650
651impl HttpResponseError {
652 fn v1_to_v2(self) -> Result<Self> {
653 let Self::V1(data) = self else {
654 bail!("expected client protocol v1 HttpResponseError")
655 };
656 Ok(Self::V2(data.into()))
657 }
658
659 fn v2_to_v3(self) -> Result<Self> {
660 let Self::V2(data) = self else {
661 bail!("expected client protocol v2 HttpResponseError")
662 };
663 Ok(Self::V3(data.into()))
664 }
665
666 fn v3_to_v4(self) -> Result<Self> {
667 let Self::V3(data) = self else {
668 bail!("expected client protocol v3 HttpResponseError")
669 };
670 Ok(Self::V4(v4::HttpResponseError {
671 group: data.group,
672 code: data.code,
673 message: data.message,
674 metadata: data.metadata,
675 actor: None,
676 }))
677 }
678
679 fn v4_to_v3(self) -> Result<Self> {
680 let Self::V4(data) = self else {
681 bail!("expected client protocol v4 HttpResponseError")
682 };
683 Ok(Self::V3(v3::HttpResponseError {
684 group: data.group,
685 code: data.code,
686 message: data.message,
687 metadata: data.metadata,
688 }))
689 }
690
691 fn v3_to_v2(self) -> Result<Self> {
692 let Self::V3(data) = self else {
693 bail!("expected client protocol v3 HttpResponseError")
694 };
695 Ok(Self::V2(data.into()))
696 }
697
698 fn v2_to_v1(self) -> Result<Self> {
699 let Self::V2(data) = self else {
700 bail!("expected client protocol v2 HttpResponseError")
701 };
702 Ok(Self::V1(data.into()))
703 }
704}