dcl_rpc/rpc_protocol/
mod.rs

1//! Contains the types and functions needed to use the Decentraland RPC implementation.
2pub mod parse;
3// proto file definition doesn't have a package name, so it defaults to "_"
4// TODO: scope the protcolol just to the crate
5include!(concat!(env!("OUT_DIR"), "/_.rs"));
6
7/// This trait should me implemented by the Error type returned in your server's procedures
8///
9/// # Example
10///
11/// ```
12/// use dcl_rpc::rpc_protocol::{RemoteError, RemoteErrorResponse};
13/// pub enum MyEnumOfErrors {
14///     EntityNotFound,
15///     DbError
16/// }
17///
18/// impl RemoteErrorResponse for MyEnumOfErrors {
19///     fn error_code(&self) -> u32 {
20///         match self {
21///             Self::EntityNotFound => 404,
22///             Self::DbError => 500
23///         }
24///     }
25///     
26///     fn error_message(&self) -> String {
27///         match self {
28///             Self::EntityNotFound => "The entity wasn't found".to_string(),
29///             Self::DbError => "Internal Server Error".to_string()
30///         }
31///     }
32/// }
33///
34/// let error: RemoteError = MyEnumOfErrors::EntityNotFound.into();
35/// assert_eq!(error.error_code, 404);
36/// assert_eq!(error.error_message, "The entity wasn't found")
37/// ```
38///
39///
40pub trait RemoteErrorResponse {
41    fn error_code(&self) -> u32;
42    fn error_message(&self) -> String;
43}
44
45/// Every type which implements [`RemoteErrorResponse`], it can be turned into a [`RemoteError`]
46impl<T: RemoteErrorResponse> From<T> for RemoteError {
47    fn from(value: T) -> Self {
48        Self {
49            message_identifier: 0, // We cannot know the identifier, it has to be changed after.
50            error_code: value.error_code(),
51            error_message: value.error_message(),
52        }
53    }
54}
55
56/// This functions works for filling a [`RemoteError`]. This is needed because:
57///
58/// When a server procedure returns a custom type as an error, which has to implement [`RemoteErrorResponse`](`super::RemoteErrorResponse`).
59///
60/// That custom type is then turned into a [`RemoteError`] but without a "true" value (`0`) in the `message_identifier` field
61///
62/// Because at the moment of conversion, the `message_number` is not available so the [`RemoteError`] has to be filled then.
63///
64pub(crate) fn fill_remote_error(remote_error: &mut RemoteError, message_number: u32) {
65    remote_error.message_identifier = parse::build_message_identifier(
66        RpcMessageTypes::RemoteErrorResponse as u32,
67        message_number,
68    );
69}
70
71/// Build the [`ServerReady`](`RpcMessageTypes::ServerReady`) message for the client
72pub(crate) fn server_ready_message() -> RpcMessageHeader {
73    RpcMessageHeader {
74        message_identifier: parse::build_message_identifier(RpcMessageTypes::ServerReady as u32, 0),
75    }
76}