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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//! Xous supports sending Messages from Clients to Servers. If a message is
//! a `MemoryMessage`, then the Server may respond by updating the buffer
//! with a response message and returning the buffer.
//!
//! A number of serialization options are available, ranging from sending
//! raw arrays of bytes all the way to sending full Protobuf messages.
//!
//! This crate takes a middle road and allows for sending rich Rust types
//! such as full enums and structs without doing extensive checks. This is
//! based on the theory that in normal operating systems, ABIs do not contain
//! any sort of verification, and it is undefined behaviour to send a malformed
//! request to a loaded module.
//!
//! An object can be made into an IPC object by implementing the `Ipc` trait.
//! The primary method of doing this is by adding `#[derive(flatipc::Ipc)]`
//! to the definition. Such an object may be included in both the Client and
//! the Server so that they share the same view of the object.
//!
//! Any object may be made into an IPC object provided it follows the following
//! requirements:
//!
//! - **The object is `#[repr(C)]`** - This is required to ensure the objecty
//! has a well-defined layout in memory. Other representations may shift
//! depending on optimizations.
//! - **The object only contains fields that are `IpcSafe`** - This trait is
//! implemented on primitive types that are able to be sent across an IPC
//! boundary. This includes all integers, floats, and booleans. It also
//! includes arrays of `IpcSafe` types, `Option<T>` where `T` is `IpcSafe`,
//! and `Result<T, E>` where `T` and `E` are `IpcSafe`. Pointers and
//! references are not `IpcSafe` and may not be used.
//!
//! When deriving `Ipc`, a new type will be created with the same name as
//! the original type prefixed with `Ipc`. For example, if you derive `Ipc`
//! on a type named `Foo`, the new type will be named `IpcFoo`.
//!
//! Objects that implement `Ipc` must be page-aligned and must be a full multiple
//! of a page size in length. This is to ensure that the object can be mapped
//! transparently between the Client and the Server without dragging any extra
//! memory along with it.
//!
//! `Ipc` objects implement `Deref` and `DerefMut` to the original object, so
//! they can be used in place of the original object in most cases by derefencing
//! the `Ipc` object.
//!
//! Because `String` and `Vec` contain pointers, they are not `IpcSafe`. As such,
//! replacements are made available in this crate that are `IpcSafe`.
//!
//! <br>
//!
//! # Example of a Derived Ipc Object
//!
//! ```ignore
//! #[repr(C)]
//! #[derive(flatipc::Ipc)]
//! pub struct Foo {
//! a: u32,
//! b: u64,
//! }
//!
//! // Connect to an example server
//! let conn = xous::connect(xous::SID::from_bytes(b"example---server").unwrap())?;
//!
//! // Construct our object
//! let foo = Foo { a: 1, b: 1234567890 };
//!
//! // Create an IPC representation of the original object, consuming
//! // the original object in the process.
//! let mut foo_ipc = foo.into_ipc();
//!
//! // Lend the object to the server with opcode 42.
//! foo_ipc.lend(conn, 42)?;
//!
//! // Note that we can still access the original object.
//! println!("a: {}", foo_ipc.a);
//!
//! // When we're done with the IPC object, we can get the original object back.
//! let foo = foo_ipc.into_original();
//! ```
//!
//! # Example of Server Usage
//!
//! ```ignore
//! // Ideally this comes from a common `API` file that both the
//! // client and server share.
//! #[repr(C)]
//! #[derive(flatipc::Ipc)]
//! pub struct Foo {
//! a: u32,
//! b: u64,
//! }
//!
//! let mut msg_opt = None;
//! let mut server = xous::create_server_with_sid(b"example---server").unwrap();
//! loop {
//! let envelope = xous::reply_and_receive_next(server, &mut msg_opt).unwrap();
//! let Some(msg) = msg_opt else { continue };
//!
//! // Take the memory portion of the message, continuing if it's not a memory message.
//! let Some(msg_memory) = msg.memory_message() else { continue };
//!
//! // Turn the `MemoryMessage` into an `IpcFoo` object. Note that this is the `Ipc`-prefixed
//! // version of the original object. If the object is not the correct type, `None` will be
//! // returned and the message will be returned to the sender in ghe next loop.
//! let Some(foo) = IpcFoo::from_memory_message(msg_slice, signature) else { continue };
//!
//! // Do something with the object.
//! }
//! ```
/// An object is Sendable if it is guaranteed to be flat and contains no pointers.
/// This trait can be placed on objects that have invalid representations such as
/// bools (which can only be 0 or 1) but it is up to the implementer to ensure that
/// the correct object arrives on the other side.
pub unsafe
// Enable calling this crate as `flatipc` in tests.
extern crate self as flatipc;
// Allow doing `#[derive(flatipc::Ipc)]` instead of `#[derive(flatipc_derive::Ipc)]`
pub use ;
pub use ;
pub use String;
pub use Vec;
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
/// An object that can be sent across an IPC boundary, and can be reconstituted
/// on the other side without copying. An object with this trait must be page-aligned,
/// must be a multiple of the page size in length, and must not contain any pointers.
pub unsafe
/// Objects that have `IntoIpc` may be turned into an object that can be passed
/// across an IPC barrier. This consumes the object and returns a new object that
/// may be dereferenced to the original object.