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
extern crate alloc;
use crate::r#yield;
use alloc::vec::Vec;
use cstr_core::{c_char, CString};
extern "C" {
fn ipc_publish(topic: *const c_char, msg_ptr: *mut u8, msg_len: usize) -> usize;
fn ipc_subscribe(topic: *const c_char) -> usize;
fn ipc_unsubscribe(topic: *const c_char) -> usize;
fn ipc_get_message(topic: *const c_char, block: bool) -> Message;
}
#[repr(C)]
pub struct Message {
pub msg_ptr: *mut u8,
pub msg_len: usize,
pub valid: bool,
}
impl From<Vec<u8>> for Message {
fn from(mut item: Vec<u8>) -> Self {
item.shrink_to_fit();
let (msg_ptr, msg_len, _msg_cap) = item.into_raw_parts();
Message {
msg_ptr,
msg_len,
valid: true,
}
}
}
impl Into<Vec<u8>> for Message {
fn into(self) -> Vec<u8> {
unsafe { Vec::from_raw_parts(self.msg_ptr, self.msg_len, self.msg_len) }
}
}
pub struct Publisher {
pub topic: CString,
}
impl Publisher {
pub fn new(topic: &str) -> Result<Self, &'static str> {
let c_topic = match CString::new(topic) {
Ok(t) => t,
Err(_) => return Err("Invalid topic string"),
};
Ok(Publisher { topic: c_topic })
}
pub fn publish(&mut self, mut message: Vec<u8>) -> Result<(), &'static str> {
message.shrink_to_fit();
let (msg_ptr, msg_len, _msg_cap) = message.into_raw_parts();
let success = unsafe { ipc_publish((&self.topic).as_ptr(), msg_ptr, msg_len) };
if success == 0 {
r#yield();
Ok(())
} else {
Err("Unable to publish to topic.")
}
}
}
pub struct Subscriber {
pub topic: CString,
}
impl Subscriber {
pub fn new(topic: &str) -> Result<Self, &'static str> {
let c_topic = match CString::new(topic) {
Ok(t) => t,
Err(_) => return Err("Invalid topic string"),
};
let new_sub = Subscriber { topic: c_topic };
let resp = unsafe { ipc_subscribe((&new_sub.topic).as_ptr()) };
if resp == 1 {
Err("Failed to subscribe to topic.")
} else {
Ok(new_sub)
}
}
fn get_message_base(&mut self, block: bool) -> Option<Vec<u8>> {
let message: Message = unsafe { ipc_get_message((&self.topic).as_ptr(), block) };
if message.valid {
Some(message.into())
} else {
None
}
}
pub fn get_message(&mut self) -> Option<Vec<u8>> {
self.get_message_base(true)
}
pub fn get_message_nonblocking(&mut self) -> Option<Vec<u8>> {
self.get_message_base(false)
}
}
impl Drop for Subscriber {
fn drop(&mut self) {
unsafe {
ipc_unsubscribe((&self.topic).as_ptr());
}
}
}