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
use futures::Future;

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

use super::{
	error::{Error, Result, Serde, UnexpectedType},
	get_type_id,
	handle::{Fail, Request, With},
	FromBytes, ToBytes,
};

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

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

pub trait HandleBytes {
	type Handle<'a>: Future<Output = Result<Vec<u8>>> + 'a
	where
		Self: 'a;
	fn handle_bytes<'a>(&'a self, req: &'a [u8]) -> Self::Handle<'a>;
}

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

impl<T> HandleBytes for T
where
	T: Handles,
{
	type Handle<'a> = impl Future<Output = Result<Vec<u8>>> + 'a
	where
		Self: 'a;

	fn handle_bytes<'a>(&'a self, req: &'a [u8]) -> Self::Handle<'a> {
		async move {
			T::List::handle(self, req).await.ok_or_else(|| {
				Error::<Serde>::from(UnexpectedType(
					match get_type_id(req) {
						Ok(id) => id,
						Err(e) => return e,
					}
					.to_string(),
				))
			})?
		}
	}
}

impl<H> HandleList<H> for Fail {
	async fn handle(_: &H, _: &[u8]) -> Option<Result<Vec<u8>>> {
		None
	}
}

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