1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use std::marker::PhantomData;

use futures::Future;

use crate::{errorx::Scope, ResultExt};

use super::{
	error::{Error, Serde, UnexpectedType},
	get_type_id, FromBytes, ToBytes,
};

pub trait Request {
	type Response;
}

impl Request for &[u8] {
	type Response = Vec<u8>;
}

pub trait Handles<Cx>: Sized {
	type List: HandleList<Self, Cx>;
}

pub trait HandlesSend<Cx>: Handles<Cx> {
	fn handle<'a>(
		self,
		req: &'a [u8],
		cx: Cx,
	) -> impl Future<Output = Result<Vec<u8>, Error<impl Scope + 'a>>> + Send + 'a
	where
		Cx: 'a;
}

mod send {
	use futures::Future;

	use crate::{serde::error::Error, FixSend};

	use super::{Handles, HandlesSend};

	type Scope<'a, T, Cx>
	where
		T: super::Handle<Cx, &'a [u8]> + 'a,
		Cx: 'a,
	= impl crate::errorx::Scope + 'a;
	pub type HandleSend<'a, T, Cx>
	where
		T: super::Handle<Cx, &'a [u8]> + 'a,
		Cx: 'a,
	= impl Future<Output = Result<Vec<u8>, Error<Scope<'a, T, Cx>>>> + 'a;
	pub fn handle_send<'a, T, Cx>(v: T, req: &'a [u8], cx: Cx) -> HandleSend<'a, T, Cx>
	where
		T: super::Handle<Cx, &'a [u8]> + 'a,
		Cx: 'a,
	{
		super::Handle::handle(v, req, cx)
	}

	impl<T, Cx> HandlesSend<Cx> for T
	where
		for<'a> T: Handles<Cx> + super::Handle<Cx, &'a [u8]> + Send + 'a,
		for<'a> HandleSend<'a, T, Cx>: Send,
		Cx: Send,
	{
		fn handle<'a>(
			self,
			req: &'a [u8],
			cx: Cx,
		) -> impl Future<Output = Result<Vec<u8>, Error<impl crate::errorx::Scope + 'a>>> + Send + 'a
		where
			Cx: 'a,
		{
			FixSend(async move { super::Handle::handle(self, req, cx).await })
		}
	}
}

pub use send::*;

pub trait Handle<Cx, Req>
where
	Req: Request,
{
	async fn handle(self, req: Req, cx: Cx) -> Result<Req::Response, Error<impl Scope>>;
}

pub trait HandleList<H, Cx> {
	async fn handle(handler: H, req: &[u8], cx: Cx) -> Result<Result<Vec<u8>, Error>, (H, Cx)>;
}

impl<T, Cx> Handle<Cx, &[u8]> for T
where
	T: Handles<Cx>,
{
	async fn handle(
		self,
		req: &[u8],
		cx: Cx,
	) -> Result<<&[u8] as Request>::Response, Error<impl Scope>> {
		T::List::handle(self, req, cx).await.map_err(|_| {
			Error::<Serde>::from(UnexpectedType(
				match get_type_id(req) {
					Ok(id) => id,
					Err(e) => return e,
				}
				.to_string(),
			))
		})?
	}
}

pub struct Fail;

impl<H, Cx> HandleList<H, Cx> for Fail {
	async fn handle(handler: H, _: &[u8], cx: Cx) -> Result<Result<Vec<u8>, Error>, (H, Cx)> {
		Err((handler, cx))
	}
}

pub struct With<Req, Prev>(PhantomData<dyn Fn(Prev, Req)>);

impl<H, Cx, Req, Prev> HandleList<H, Cx> for With<Req, Prev>
where
	H: Handle<Cx, Req>,
	Req: Request + for<'a> FromBytes<'a>,
	Prev: HandleList<H, Cx>,
	Req::Response: ToBytes,
{
	async fn handle(handler: H, req: &[u8], cx: Cx) -> Result<Result<Vec<u8>, Error>, (H, Cx)> {
		match Req::from_bytes(req) {
			Ok(req) => Ok(handler
				.handle(req, cx)
				.await
				.err_into()
				.and_then(|x| x.to_bytes().err_into())),
			Err(_) => Prev::handle(handler, req, cx).await,
		}
	}
}

#[macro_export]
macro_rules! Handle {
	[] => { $crate::serde::handle::Fail };
	[$t0:ty] => { $crate::serde::handle::With<$t0, $crate::serde::handle::Fail> };
	[$t0:ty; $other:ty] => { $crate::serde::handle::With<$t0, $other> };
	[$t0:ty, $($tn:ty),*] => { $crate::serde::handle::With<$t0, $crate::Handle![$($tn),*]> };
	[$t0:ty, $($tn:ty),*; $other:ty] => { $crate::serde::handle::With<$t0, $crate::Handle![$($tn),*; $other]> };
}