urpc/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2
3//! uRPC (pronounced micro RPC) is a simple and lightweight RPC framework designed with embedded
4//! systems in mind.  The server side works in a heapless environment with `no_std` and is
5//! supposed to use very low resources.  The current client side implementation requires `std`.
6//!
7//! # Features
8//!
9//! - ✓ Support for 256 different methods.
10//! - ✓ Low level primitives for the server side regarding request parsing and
11//!   reply serializing.
12//! - ✓ Single argument of any `sedre::Serialize + serde::DeserializeOwned` type.
13//! - ✓ Optional byte buffer for the argument that doesn't involve any buffer copy.
14//!     - This feature is designed to optimize the transfer of bytes between client
15//!       and server minimizing the amount of used memory in the server.
16//! - ✓ Single return value of any `sedre::Serialize + serde::DeserializeOwned` type.
17//! - ✓ Optional byte buffer for the reply ~~that doesn't involve any buffer copy~~.
18//!     - This feature is designed to optimize the transfer of bytes between client
19//!       and server ~~minimizing the amount of used memory in the client~~.
20//! - ✗ Methods can return custom errors.
21//! - ✗ Asyncrhonous methods.
22//!     - ✗ Support for holding 255 async uncompleted requests.
23//! - ✗ Stream methods.
24//!
25//! # Packet format
26//!
27//! - The request packet consists of a 7 byte header, an optional body and an
28//!   optional byte buffer.
29//! - The reply packet consists of a 6 byte header, an optional body and an
30//!   optional byte buffer.
31//!
32//! # Header Format
33//!
34//! ## Request
35//!
36//! length | desc
37//! -------|-----
38//! 8b | method index
39//! 8b | channel id
40//! 8b | options
41//! 16b | body length (little endian)
42//! 16b | optional buffer length (little endian)
43//!
44//! ## Reply
45//!
46//! length | desc
47//! -------|-----
48//! 8b | channel id
49//! 8b | options
50//! 16b | body length (little endian)
51//! 16b | optional buffer length (little endian)
52//!
53//! # Usage
54//!
55//! The best way to use this library is by using the macros `server_requets` and `client_requests`.
56//! You can see complete examples in the documentation: [server_requests](macro.server_requests.html),
57//! [client_requests](macro.client_requests.html).
58
59#[macro_use]
60mod macros;
61
62#[cfg(feature = "std")]
63/// Client side implementation
64pub mod client;
65
66/// Constant parameters
67pub mod consts;
68
69/// Server side implementation
70pub mod server;
71
72use postcard::from_bytes;
73use serde::{Deserialize, Serialize};
74
75// Auto
76// enum Error {
77//     InvalidMethod,
78//     InvalidBody,
79//     Busy,
80// }
81
82// pub type Result<T> = postcard::Result<T>;
83// pub type Error = postcard::Error;
84
85/// Options of a request/reply packet
86#[derive(Serialize, Deserialize, Clone, Debug)]
87pub struct Opts {
88    pub sync: bool,
89    pub once: bool,
90    pub cancel: bool,
91}
92
93/// Header of a request packet
94#[derive(Serialize, Deserialize, Clone, Debug)]
95pub struct RequestHeader {
96    pub method_idx: u8,
97    chan_id: u8,
98    opts: u8,
99    body_len: u16,
100    buf_len: u16,
101}
102
103impl RequestHeader {
104    pub fn body_len(&self) -> usize {
105        self.body_len as usize
106    }
107    pub fn buf_len(&self) -> usize {
108        self.buf_len as usize
109    }
110}
111
112/// Header of a reply packet
113#[derive(Serialize, Deserialize, Clone, Debug)]
114pub struct ReplyHeader {
115    chan_id: u8,
116    opts: u8,
117    body_len: u16,
118    buf_len: u16,
119}
120
121impl ReplyHeader {
122    pub fn body_len(&self) -> usize {
123        self.body_len as usize
124    }
125    pub fn buf_len(&self) -> usize {
126        self.buf_len as usize
127    }
128}
129
130// enum ReplyType {
131//     Ack,
132//     Error,
133//     Data,
134// }
135
136fn req_header_from_bytes(buf: &[u8]) -> Result<RequestHeader, postcard::Error> {
137    from_bytes(buf)
138}
139
140fn rep_header_from_bytes(buf: &[u8]) -> Result<ReplyHeader, postcard::Error> {
141    from_bytes(buf)
142}
143
144/// Trait used to allow building RPC calls with optional buffer.
145pub trait OptBuf {
146    fn opt_buf() -> bool;
147}
148
149/// Indicate that the RPC Call contains an optional buffer.
150#[derive(Debug)]
151pub struct OptBufYes {}
152impl OptBuf for OptBufYes {
153    fn opt_buf() -> bool {
154        true
155    }
156}
157
158/// Indicate that the RPC Call doesn't contain an optional buffer.
159#[derive(Debug)]
160pub struct OptBufNo {}
161impl OptBuf for OptBufNo {
162    fn opt_buf() -> bool {
163        false
164    }
165}