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//! ![PubNub](https://raw.githubusercontent.com/pubnub/rust/master/logo.svg)
9//!
10//! ![Tests](https://github.com/pubnub/rust/actions/workflows/run-tests.yml/badge.svg)
11//! ![Validations](https://github.com/pubnub/rust/actions/workflows/run-validations.yml/badge.svg)
12//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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}