Skip to content

Commit 1e15d07

Browse files
authored
presence & no_std (#172)
1 parent 3483fb6 commit 1e15d07

File tree

13 files changed

+451
-10
lines changed

13 files changed

+451
-10
lines changed

examples/no_std/Cargo.toml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
pubnub = { path = "../../", default_features = false, features = ["blocking", "serde", "publish", "subscribe"] }
9+
pubnub = { path = "../../", default_features = false, features = ["blocking", "serde", "publish", "subscribe", "presence"] }
1010
serde = { version = "1.0", default_features = false, features = ["derive"] }
1111
getrandom = { version = "0.2", default_features = false, features = ["custom"] }
1212

@@ -17,3 +17,16 @@ path = "src/publish.rs"
1717
[[bin]]
1818
name = "subscribe"
1919
path = "src/subscribe.rs"
20+
21+
[[bin]]
22+
name = "here_now"
23+
path = "src/here_now.rs"
24+
25+
[[bin]]
26+
name = "where_now"
27+
path = "src/where_now.rs"
28+
29+
[[bin]]
30+
name = "presence_state"
31+
path = "src/presence_state.rs"
32+

examples/no_std/src/here_now.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Warning: This example is compiling for target `thumbv7m-none-eabi`
2+
// but have never been tested for this target.
3+
//
4+
// Treat it as a reference only!
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
extern crate alloc;
10+
11+
use core::{
12+
alloc::{GlobalAlloc, Layout},
13+
panic::PanicInfo,
14+
};
15+
16+
use pubnub::{
17+
core::{
18+
transport::{blocking::Transport, PUBNUB_DEFAULT_BASE_URL},
19+
transport_request::TransportRequest,
20+
transport_response::TransportResponse,
21+
PubNubError,
22+
},
23+
Keyset, PubNubClientBuilder,
24+
};
25+
26+
// As getrandom crate has limited support of targets, we need to provide custom
27+
// implementation of `getrandom` function.
28+
getrandom::register_custom_getrandom!(custom_random);
29+
fn custom_random(buf: &mut [u8]) -> Result<(), getrandom::Error> {
30+
// We're using `42` as a random number, because it's the answer
31+
// to the Ultimate Question of Life, the Universe, and Everything.
32+
// In your program, you should use proper random number generator that is supported by your target.
33+
for i in buf.iter_mut() {
34+
*i = 42;
35+
}
36+
37+
Ok(())
38+
}
39+
40+
// Many targets have very specific requirements for networking, so it's hard to
41+
// provide a generic implementation.
42+
// Depending on the target, you will probably need to implement `Transport` trait.
43+
struct MyTransport;
44+
45+
impl Transport for MyTransport {
46+
fn send(&self, _: TransportRequest) -> Result<TransportResponse, PubNubError> {
47+
let _hostname = PUBNUB_DEFAULT_BASE_URL;
48+
49+
// Send your request here
50+
51+
Ok(TransportResponse::default())
52+
}
53+
}
54+
55+
// As our target does not have `std` library, we need to provide custom
56+
// implementation of `GlobalAlloc` trait.
57+
//
58+
// In your program, you should use proper allocator that is supported by your target.
59+
// Here you have dummy implementation that does nothing.
60+
#[derive(Default)]
61+
pub struct Allocator;
62+
63+
unsafe impl GlobalAlloc for Allocator {
64+
unsafe fn alloc(&self, _: Layout) -> *mut u8 {
65+
core::ptr::null_mut()
66+
}
67+
unsafe fn dealloc(&self, _: *mut u8, _layout: Layout) {}
68+
}
69+
70+
#[global_allocator]
71+
static GLOBAL_ALLOCATOR: Allocator = Allocator;
72+
73+
// As our target does not have `std` library, we need to provide custom
74+
// implementation of `panic_handler`.
75+
//
76+
// In your program, you should use proper panic handler that is supported by your target.
77+
// Here you have dummy implementation that does nothing.
78+
#[panic_handler]
79+
fn panicking(_: &PanicInfo) -> ! {
80+
loop {}
81+
}
82+
83+
// As we're using `no_main` attribute, we need to define `main` function manually.
84+
// For this example we're using `extern "C"` ABI to make it work.
85+
#[no_mangle]
86+
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> usize {
87+
publish_example().map(|_| 0).unwrap()
88+
}
89+
90+
// In standard subscribe examples we use `println` macro to print the result of the operation
91+
// and it shows the idea of the example. `no_std` does not support `println` macro,
92+
// so we're using `do_a_thing` function instead.
93+
fn do_a_thing<T>(_: &T) {}
94+
95+
// As `no_std` does not support `Error` trait, we use `PubNubError` instead.
96+
// In your program, you should handle the error properly for your use case.
97+
fn publish_example() -> Result<(), PubNubError> {
98+
// As `no_std` does not support `env::var`, you need to set the keys manually.
99+
let publish_key = "SDK_PUB_KEY";
100+
let subscribe_key = "SDK_SUB_KEY";
101+
102+
let client = PubNubClientBuilder::with_blocking_transport(MyTransport)
103+
.with_keyset(Keyset {
104+
subscribe_key,
105+
publish_key: Some(publish_key),
106+
secret_key: None,
107+
})
108+
.with_user_id("user_id")
109+
.build()?;
110+
111+
let channels_now = client
112+
.here_now()
113+
.channels(["my_channel".into(), "other_channel".into()].to_vec())
114+
.include_state(true)
115+
.include_user_id(true)
116+
.execute_blocking()?;
117+
118+
// As `no_std` does not support `println` macro, we're using `do_a_thing` function instead
119+
// to show possible usage of the result.
120+
121+
channels_now.iter().for_each(|channel| {
122+
do_a_thing(&channel.name);
123+
do_a_thing(&channel.occupancy);
124+
do_a_thing(&channel.occupants);
125+
126+
channel
127+
.occupants
128+
.iter()
129+
.for_each(|occupant| do_a_thing(occupant));
130+
});
131+
132+
Ok(())
133+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Warning: This example is compiling for target `thumbv7m-none-eabi`
2+
// but have never been tested for this target.
3+
//
4+
// Treat it as a reference only!
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
extern crate alloc;
10+
11+
use core::{
12+
alloc::{GlobalAlloc, Layout},
13+
panic::PanicInfo,
14+
};
15+
16+
use alloc::string::String;
17+
use pubnub::{
18+
core::{
19+
transport::{blocking::Transport, PUBNUB_DEFAULT_BASE_URL},
20+
transport_request::TransportRequest,
21+
transport_response::TransportResponse,
22+
PubNubError,
23+
},
24+
Keyset, PubNubClientBuilder,
25+
};
26+
use serde::Serialize;
27+
28+
#[derive(Debug, Serialize)]
29+
struct State {
30+
is_doing: String,
31+
}
32+
33+
// As getrandom crate has limited support of targets, we need to provide custom
34+
// implementation of `getrandom` function.
35+
getrandom::register_custom_getrandom!(custom_random);
36+
fn custom_random(buf: &mut [u8]) -> Result<(), getrandom::Error> {
37+
// We're using `42` as a random number, because it's the answer
38+
// to the Ultimate Question of Life, the Universe, and Everything.
39+
// In your program, you should use proper random number generator that is supported by your target.
40+
for i in buf.iter_mut() {
41+
*i = 42;
42+
}
43+
44+
Ok(())
45+
}
46+
47+
// Many targets have very specific requirements for networking, so it's hard to
48+
// provide a generic implementation.
49+
// Depending on the target, you will probably need to implement `Transport` trait.
50+
struct MyTransport;
51+
52+
impl Transport for MyTransport {
53+
fn send(&self, _: TransportRequest) -> Result<TransportResponse, PubNubError> {
54+
let _hostname = PUBNUB_DEFAULT_BASE_URL;
55+
56+
// Send your request here
57+
58+
Ok(TransportResponse::default())
59+
}
60+
}
61+
62+
// As our target does not have `std` library, we need to provide custom
63+
// implementation of `GlobalAlloc` trait.
64+
//
65+
// In your program, you should use proper allocator that is supported by your target.
66+
// Here you have dummy implementation that does nothing.
67+
#[derive(Default)]
68+
pub struct Allocator;
69+
70+
unsafe impl GlobalAlloc for Allocator {
71+
unsafe fn alloc(&self, _: Layout) -> *mut u8 {
72+
core::ptr::null_mut()
73+
}
74+
unsafe fn dealloc(&self, _: *mut u8, _layout: Layout) {}
75+
}
76+
77+
#[global_allocator]
78+
static GLOBAL_ALLOCATOR: Allocator = Allocator;
79+
80+
// As our target does not have `std` library, we need to provide custom
81+
// implementation of `panic_handler`.
82+
//
83+
// In your program, you should use proper panic handler that is supported by your target.
84+
// Here you have dummy implementation that does nothing.
85+
#[panic_handler]
86+
fn panicking(_: &PanicInfo) -> ! {
87+
loop {}
88+
}
89+
90+
// As we're using `no_main` attribute, we need to define `main` function manually.
91+
// For this example we're using `extern "C"` ABI to make it work.
92+
#[no_mangle]
93+
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> usize {
94+
publish_example().map(|_| 0).unwrap()
95+
}
96+
97+
// In standard subscribe examples we use `println` macro to print the result of the operation
98+
// and it shows the idea of the example. `no_std` does not support `println` macro,
99+
// so we're using `do_a_thing` function instead.
100+
fn do_a_thing<T>(_: &T) {}
101+
102+
// As `no_std` does not support `Error` trait, we use `PubNubError` instead.
103+
// In your program, you should handle the error properly for your use case.
104+
fn publish_example() -> Result<(), PubNubError> {
105+
// As `no_std` does not support `env::var`, you need to set the keys manually.
106+
let publish_key = "SDK_PUB_KEY";
107+
let subscribe_key = "SDK_SUB_KEY";
108+
109+
let client = PubNubClientBuilder::with_blocking_transport(MyTransport)
110+
.with_keyset(Keyset {
111+
subscribe_key,
112+
publish_key: Some(publish_key),
113+
secret_key: None,
114+
})
115+
.with_user_id("user_id")
116+
.build()?;
117+
118+
// As `no_std` does not support `println` macro, we're using `do_a_thing` function instead
119+
// to show possible usage of the result.
120+
121+
client
122+
.set_presence_state(State {
123+
is_doing: "Nothing... Just hanging around...".into(),
124+
})
125+
.channels(["my_channel".into(), "other_channel".into()].to_vec())
126+
.user_id("user_id")
127+
.execute_blocking()?;
128+
129+
let states = client
130+
.get_presence_state()
131+
.channels(["my_channel".into(), "other_channel".into()].to_vec())
132+
.user_id("user_id")
133+
.execute_blocking()?;
134+
135+
do_a_thing(&states);
136+
137+
states.iter().for_each(|channel| {
138+
do_a_thing(&channel.channel);
139+
do_a_thing(&channel.state);
140+
});
141+
142+
Ok(())
143+
}

0 commit comments

Comments
 (0)