Skip to main content

uni_components/
service.rs

1use uniui_core::Slot;
2
3use crate::{
4	to_path,
5	CallError,
6	Kind,
7	Response,
8};
9
10/// Represents server side handler.
11///
12/// It's a good idea to use [define_service!](crate::define_service!) instead of trying to
13/// implement the trait by yourself.
14pub trait Service {
15	/// Input parameter type (There are special limitations for [Kind::Get] requests
16	type In: 'static + serde::de::DeserializeOwned + serde::Serialize;
17
18	/// Output parameter type
19	type Out: 'static + serde::de::DeserializeOwned + serde::Serialize;
20
21	/// Path to the handler at service
22	fn path(&self) -> &str;
23
24	/// The kind of requests service will process
25	fn kind(&self) -> Kind;
26
27	/// Converter from HTTP response to Service's output type
28	fn from_response(&self) -> fn(response: Response) -> Result<Self::Out, Response>;
29
30	/// Executes the service. Default implementation call related to the `path` at
31	/// server side.
32	///
33	/// parameter - input parameter
34	///
35	/// slot - will receive result of the server call
36	fn exec(
37		&self,
38		parameter: &Self::In,
39		slot: &dyn Slot<Result<Self::Out, Response>>,
40	) -> Result<(), CallError> {
41		let p = parameter;
42		let s = slot.proxy();
43
44		let converter = self.from_response();
45		let cpa = move |code, body: String| {
46			let result = Response {
47				code,
48				body: Some(body.into()),
49			};
50			let data = converter(result);
51			s.exec_for(data);
52		};
53
54		return match self.kind() {
55			Kind::Get => {
56				let path = to_path(self.path(), p)?;
57				uni_net::get(&path, cpa)?;
58				Ok(())
59			},
60			Kind::Post => {
61				let data = serde_json::to_string(p)?;
62				uni_net::post_json(self.path(), &data, cpa)?;
63				Ok(())
64			},
65		};
66	}
67}