Skip to main content

zlink_core/server/
service.rs

1//! Service-related API.
2
3use core::{fmt::Debug, future::Future};
4
5use futures_util::Stream;
6use serde::{Deserialize, Serialize};
7
8use crate::{connection::Socket, Call, Connection, Reply};
9
10/// The item type that a [`Service::ReplyStream`] yields.
11///
12/// On `std`, this is a tuple of the reply and the file descriptors to send with it. On `no_std`,
13/// this is just the reply.
14#[cfg(feature = "std")]
15pub type ReplyStreamItem<Params> = (Reply<Params>, Vec<std::os::fd::OwnedFd>);
16/// The item type that a [`Service::ReplyStream`] yields.
17///
18/// On `std`, this is a tuple of the reply and the file descriptors to send with it. On `no_std`,
19/// this is just the reply.
20#[cfg(not(feature = "std"))]
21pub type ReplyStreamItem<Params> = Reply<Params>;
22
23/// Service trait for handling method calls.
24///
25/// Instead of implementing this trait manually, prefer using the [`service`] attribute macro which
26/// generates the implementation for you. The macro provides a more ergonomic API and handles the
27/// boilerplate of method dispatching, error handling, and streaming replies.
28///
29/// See the [`service`] macro documentation for details and examples.
30///
31/// [`service`]: macro@crate::service
32pub trait Service<Sock>
33where
34    Sock: Socket,
35{
36    /// The type of method call that this service handles.
37    ///
38    /// This should be a type that can deserialize itself from a complete method call message: i-e
39    /// an object containing `method` and `parameter` fields. This can be easily achieved using the
40    /// `serde::Deserialize` derive (See the code snippet in
41    /// [`crate::connection::WriteConnection::send_call`] documentation for an example).
42    type MethodCall<'de>: Deserialize<'de> + Debug;
43    /// The type of the successful reply.
44    ///
45    /// This should be a type that can serialize itself as the `parameters` field of the reply.
46    type ReplyParams<'ser>: Serialize + Debug
47    where
48        Self: 'ser;
49    /// The type of the item that [`Service::ReplyStream`] will be expected to yield.
50    ///
51    /// This should be a type that can serialize itself as the `parameters` field of the reply.
52    type ReplyStreamParams: Serialize + Debug;
53    /// The type of the multi-reply stream.
54    ///
55    /// If the client asks for multiple replies, this stream will be used to send them.
56    type ReplyStream: Stream<Item = ReplyStreamItem<Self::ReplyStreamParams>> + Unpin;
57    /// The type of the error reply.
58    ///
59    /// This should be a type that can serialize itself to the whole reply object, containing
60    /// `error` and `parameter` fields. This can be easily achieved using the `serde::Serialize`
61    /// derive (See the code snippet in [`crate::connection::ReadConnection::receive_reply`]
62    /// documentation for an example).
63    type ReplyError<'ser>: Serialize + Debug
64    where
65        Self: 'ser;
66
67    /// Handle a method call.
68    fn handle<'ser>(
69        &'ser mut self,
70        method: &'ser Call<Self::MethodCall<'_>>,
71        conn: &mut Connection<Sock>,
72        #[cfg(feature = "std")] fds: Vec<std::os::fd::OwnedFd>,
73    ) -> impl Future<
74        Output = HandleResult<Self::ReplyParams<'ser>, Self::ReplyStream, Self::ReplyError<'ser>>,
75    >;
76}
77
78/// The result of a [`Service::handle`] call.
79///
80/// On `std`, this is a tuple of the method reply and the file descriptors to send with it. On
81/// `no_std`, this is just the method reply.
82#[cfg(feature = "std")]
83pub type HandleResult<Params, ReplyStream, ReplyError> = (
84    MethodReply<Params, ReplyStream, ReplyError>,
85    Vec<std::os::fd::OwnedFd>,
86);
87/// The result of a [`Service::handle`] call.
88///
89/// On `std`, this is a tuple of the method reply and the file descriptors to send with it. On
90/// `no_std`, this is just the method reply.
91#[cfg(not(feature = "std"))]
92pub type HandleResult<Params, ReplyStream, ReplyError> =
93    MethodReply<Params, ReplyStream, ReplyError>;
94
95/// A service method call reply.
96#[derive(Debug)]
97pub enum MethodReply<Params, ReplyStream, ReplyError> {
98    /// A single reply.
99    Single(Option<Params>),
100    /// An error reply.
101    Error(ReplyError),
102    /// A multi-reply stream.
103    Multi(ReplyStream),
104}