pubnub/lib.rs
1#![warn(missing_docs)]
2#![cfg_attr(not(any(feature = "std", test)), no_std)]
3
4//! # PubNub Rust SDK
5//!
6//! <div align = "center">
7//!
8//! 
9//!
10//! 
11//! 
12//! [](https://github.com/pubnub/rust/LICENSE)
13//!
14//! **Make your app come alive with real-time experiences!**
15//!
16//! </div>
17//!
18//! ## Overview
19//!
20//! This is the official PubNub Rust SDK repository.
21//!
22//! [PubNub](https://www.pubnub.com/) takes care of the infrastructure and APIs needed for the realtime
23//! communication layer of your application. Work on your app's logic and let
24//! PubNub handle sending and receiving data across the world in less than
25//! 100ms.
26//!
27//! ## Getting started
28//!
29//! Below you can find everything you need to start messaging!
30//!
31//! ### Get PubNub keys
32//!
33//! You will need the publish and subscribe keys to authenticate your app. Get your keys from the [Admin Portal](https://dashboard.pubnub.com/login).
34//!
35//! ### Import using [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)
36//!
37//! Add `pubnub` to your Rust project in the `Cargo.toml` file:
38//!
39//! ```toml
40//! # default features
41//! [dependencies]
42//! pubnub = "0.7.0"
43//!
44//! # all features
45//! [dependencies]
46//! pubnub = { version = "0.7.0", features = ["full"] }
47//! ```
48//!
49//! ### Example
50//!
51//! Try the following sample code to get up and running quickly!
52//!
53//! ```no_run
54//! use pubnub::subscribe::Subscriber;
55//! use futures::StreamExt;
56//! use tokio::time::sleep;
57//! use std::time::Duration;
58//! use serde_json;
59//! use pubnub::{
60//! dx::subscribe::Update,
61//! subscribe::EventSubscriber,
62//! Keyset, PubNubClientBuilder,
63//! };
64//! #[tokio::main]
65//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
66//! use pubnub::subscribe::{EventEmitter, SubscriptionParams};
67//! let publish_key = "my_publish_key";
68//! let subscribe_key = "my_subscribe_key";
69//! let client = PubNubClientBuilder::with_reqwest_transport()
70//! .with_keyset(Keyset {
71//! subscribe_key,
72//! publish_key: Some(publish_key),
73//! secret_key: None,
74//! })
75//! .with_user_id("user_id")
76//! .build()?;
77//!
78//! println!("PubNub instance created");
79//!
80//! let subscription = client.subscription(SubscriptionParams {
81//! channels: Some(&["my_channel"]),
82//! channel_groups: None,
83//! options: None
84//! });
85//!
86//! let channel_entity = client.channel("my_channel_2");
87//! let channel_entity_subscription = channel_entity.subscription(None);
88//!
89//! subscription.subscribe();
90//! channel_entity_subscription.subscribe();
91//!
92//! println!("Subscribed to channels");
93//!
94//! // Launch a new task to print out each received message
95//! tokio::spawn(client.status_stream().for_each(|status| async move {
96//! println!("\nStatus: {:?}", status)
97//! }));
98//! tokio::spawn(subscription.stream().for_each(|event| async move {
99//! match event {
100//! Update::Message(message) | Update::Signal(message) => {
101//! // Silently log if UTF-8 conversion fails
102//! if let Ok(utf8_message) = String::from_utf8(message.data.clone()) {
103//! if let Ok(cleaned) = serde_json::from_str::<String>(&utf8_message) {
104//! println!("message: {}", cleaned);
105//! }
106//! }
107//! }
108//! Update::Presence(presence) => {
109//! println!("presence: {:?}", presence)
110//! }
111//! Update::AppContext(object) => {
112//! println!("object: {:?}", object)
113//! }
114//! Update::MessageAction(action) => {
115//! println!("message action: {:?}", action)
116//! }
117//! Update::File(file) => {
118//! println!("file: {:?}", file)
119//! }
120//! }
121//! }));
122//!
123//! // Explicitly listen only for real-time `message` updates.
124//! tokio::spawn(
125//! channel_entity_subscription
126//! .messages_stream()
127//! .for_each(|message| async move {
128//! if let Ok(utf8_message) = String::from_utf8(message.data.clone()) {
129//! if let Ok(cleaned) = serde_json::from_str::<String>(&utf8_message) {
130//! println!("message: {}", cleaned);
131//! }
132//! }
133//! }),
134//! );
135//!
136//! sleep(Duration::from_secs(2)).await;
137//!
138//! // Send a message to the channel
139//! client
140//! .publish_message("hello world!")
141//! .channel("my_channel")
142//! .r#type("text-message")
143//! .execute()
144//! .await?;
145//!
146//! // Send a message to another channel
147//! client
148//! .publish_message("hello world on the other channel!")
149//! .channel("my_channel_2")
150//! .r#type("text-message")
151//! .execute()
152//! .await?;
153//!
154//! sleep(Duration::from_secs(15)).await;
155//!
156//! Ok(())
157//! }
158//! ```
159//!
160//! You can find more examples in our [examples](https://github.com/pubnub/rust/tree/master/examples) directory!
161//!
162//! ## Features
163//!
164//! The `pubnub` crate is split into multiple features. You can enable or
165//! disable them in the `Cargo.toml` file, like so:
166//!
167//! ```toml
168//! # only blocking and access + default features
169//! [dependencies]
170//! pubnub = { version = "0.7.0", features = ["blocking", "access"] }
171//!
172//! # only parse_token + default features
173//! [dependencies]
174//! pubnub = { version = "0.7.0", features = ["parse_token"] }
175//! ```
176//!
177//! ### Available features
178//!
179//! | Feature name | Description | Available PubNub APIs |
180//! | :------------ | :---------- | :------------- |
181//! | `full` | Enables all non-conflicting features | Configuration, Publish, Subscribe, Access Manager, Parse Token, Presence, Crypto Module |
182//! | `default` | Enables default features: `publish`, `subscribe`, `serde`, `reqwest`, `std` | Configuration, Publish, Subscribe |
183//! | `publish` | Enables Publish API | Configuration, Publish |
184//! | `access` | Enables Access Manager API | Configuration, Access Manager |
185//! | `parse_token` | Enables parsing Access Manager tokens | Configuration, Parse Token |
186//! | `subscribe` | Enables Subscribe API | Configuration, Subscribe |
187//! | `presence` | Enables Presence API | Configuration, Presence |
188//! | `tokio` | Enables the [tokio](https://tokio.rs/) asynchronous runtime for Subscribe and Presence APIs | n/a |
189//! | `serde` | Uses [serde](https://github.com/serde-rs/serde) for serialization | n/a |
190//! | `reqwest` | Uses [reqwest](https://github.com/seanmonstar/reqwest) as a transport layer | n/a |
191//! | `blocking` | Enables blocking executions of APIs | n/a |
192//! | `crypto` | Enables crypto module for data encryption and decryption | n/a |
193//! | `std` | Enables `std` library | n/a |
194//!
195//! ## Documentation
196//!
197//! * [API reference for Rust](https://www.pubnub.com/docs/sdks/rust)
198//! * [Rust docs](https://www.docs.rs/pubnub/latest/pubnub)
199//!
200//! ## Wasm support
201//!
202//! The `pubnub` crate is compatible with WebAssembly. You can use it in your
203//! Wasm project.
204//!
205//! ## `no_std` support
206//!
207//! The `pubnub` crate is `no_std` compatible. To use it in a `no_std`
208//! environment, you have to disable the default features and enable the ones
209//! you need, for example:
210//!
211//! ```toml
212//! [dependencies]
213//! pubnub = { version = "0.7.0", default-features = false, features = ["serde", "publish",
214//! "blocking"] }
215//! ```
216//!
217//! ### Limitations
218//!
219//! The `no_std` support is limited by the implementation details of the SDK.
220//!
221//! The SDK uses the `alloc` crate to allocate memory for some operations, which
222//! means that certain targets aren't supported. Additionally, as we provide a
223//! synchronous API, we use some parts of the `alloc::sync` module, which is
224//! also not supported in certain `no_std` environments.
225//!
226//! Some SDK features aren't supported in a `no_std` environment:
227//!
228//! * partially `access` module (because of lack of timestamp support)
229//! * partially `reqwest` transport (because of the reqwest implementation
230//! details)
231//! * partially `subscribe` module (because of the spawning tasks and time
232//! dependence)
233//! * partially `presence` module (because of the spawning tasks and time
234//! dependence)
235//! * `std` feature (because of the `std` library)
236//!
237//! We depend on a random number generator to generate data for debugging
238//! purposes. If you want to use the SDK in a `no_std` environment, you'll have
239//! to provide your own random number generator implementation for certain
240//! targets.
241//!
242//! See more:
243//!
244//! * [`getrandom` crate](https://docs.rs/getrandom/latest/getrandom/)
245//! * [no_std examples](https://github.com/pubnub/rust/tree/master/examples/no_std/)
246//!
247//! If you're having problems compiling this crate for more exotic targets, you
248//! can try to use the `extra_platforms` feature. Be aware that this feature is
249//! **not supported** and we do not recommend using it.
250//!
251//! For more information about this feature. refer to [Cargo.toml](https://github.com/pubnub/rust/blob/master/Cargo.toml) in the `[features]` section.
252//!
253//! ## Support
254//!
255//! If you **need help** or have a **general question**, contact
256//! support@pubnub.com.
257//!
258//! ## License
259//!
260//! This project is licensed under the [MIT license](https://github.com/pubnub/rust/blob/master/LICENSE).
261
262#[cfg(feature = "access")]
263#[doc(inline)]
264pub use dx::access;
265
266#[doc(inline)]
267#[cfg(feature = "parse_token")]
268pub use dx::{parse_token, Token};
269
270#[cfg(feature = "publish")]
271#[doc(inline)]
272pub use dx::publish;
273
274#[cfg(feature = "subscribe")]
275#[doc(inline)]
276pub use dx::subscribe;
277
278#[cfg(feature = "presence")]
279#[doc(inline)]
280pub use dx::presence;
281
282#[doc(inline)]
283pub use dx::{Keyset, PubNubClientBuilder, PubNubGenericClient};
284
285#[cfg(feature = "reqwest")]
286#[doc(inline)]
287pub use dx::PubNubClient;
288
289#[cfg(feature = "std")]
290#[doc(inline)]
291pub use core::RequestRetryConfiguration;
292
293#[doc(inline)]
294pub use core::{Channel, ChannelGroup, ChannelMetadata, UserMetadata};
295pub mod core;
296pub mod dx;
297pub mod providers;
298pub mod transport;
299
300/// A facade around all the std types that we use in the library.
301/// It is used to make the library `no_std` compatible.
302mod lib {
303 #[cfg(not(feature = "std"))]
304 extern crate alloc as std_alloc;
305
306 pub(crate) mod core {
307 #[cfg(not(feature = "std"))]
308 pub(crate) use core::*;
309 #[cfg(feature = "std")]
310 pub(crate) use std::*;
311 }
312
313 pub(crate) mod alloc {
314 #[cfg(not(feature = "std"))]
315 pub(crate) use super::std_alloc::*;
316
317 #[cfg(feature = "std")]
318 pub(crate) use std::*;
319 }
320
321 pub(crate) mod collections {
322 pub(crate) use hash_map::HashMap;
323
324 pub(crate) mod hash_map {
325 //! Depending on the `std` feature, this module will re-export
326 //! either `std::collections::HashMap` or `hashbrown::HashMap`.
327 //! This is needed because there is no `no_std` HashMap available.
328 //! We decided to use `hashbrown` because it is fast and has the
329 //! same API as `std` HashMap.
330
331 #[cfg(not(feature = "std"))]
332 pub(crate) use hashbrown::HashMap;
333
334 #[cfg(feature = "std")]
335 pub(crate) use std::collections::HashMap;
336 }
337 }
338}