Skip to main content

rivetkit_client_protocol/
versioned.rs

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}