Skip to content

Commit 7f566be

Browse files
committed
refactor(channels-list): refactor duplicate removal code
Refactor code that is used for duplicated channels and groups removal to be compatible with `no_std`.
1 parent 4447e4f commit 7f566be

File tree

7 files changed

+164
-74
lines changed

7 files changed

+164
-74
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ spin = "0.9"
7979
phantom-type = { version = "0.4.2", default-features = false }
8080
percent-encoding = { version = "2.1", default-features = false }
8181
base64 = { version = "0.21", features = ["alloc"], default-features = false }
82-
derive_builder = { version = "0.20.2", default-features = false }
82+
derive_builder = { version = "0.12.0", default-features = false }
8383
uuid = { version = "1.3", features = ["v4"], default-features = false }
8484
snafu = { version = "0.7", features = ["rust_1_46"], default-features = false }
8585
rand = { version = "0.8.5", default-features = false }

src/core/utils/encoding.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::lib::alloc::{
2-
collections::HashSet,
32
string::{String, ToString},
43
vec::Vec,
54
};
@@ -77,19 +76,10 @@ pub fn join_url_encoded(strings: &[&str], sep: &str) -> Option<String> {
7776
/// Channels list used as part of URL path and therefore required.
7877
#[cfg(any(feature = "subscribe", feature = "presence"))]
7978
pub(crate) fn url_encoded_channels(channels: &[String]) -> String {
80-
let mut seen_channels = HashSet::new();
81-
8279
join_url_encoded(
8380
channels
8481
.iter()
85-
.filter_map(|channel| {
86-
let channel_string = channel.as_str();
87-
if seen_channels.insert(channel_string) {
88-
Some(channel_string)
89-
} else {
90-
None
91-
}
92-
})
82+
.map(|v| v.as_str())
9383
.collect::<Vec<&str>>()
9484
.as_slice(),
9585
",",
@@ -100,19 +90,10 @@ pub(crate) fn url_encoded_channels(channels: &[String]) -> String {
10090
/// URL-encode channel groups list.
10191
#[cfg(any(feature = "subscribe", feature = "presence"))]
10292
pub(crate) fn url_encoded_channel_groups(channel_groups: &[String]) -> Option<String> {
103-
let mut seen_groups = HashSet::new();
104-
10593
join_url_encoded(
10694
channel_groups
10795
.iter()
108-
.filter_map(|group| {
109-
let group_string = group.as_str();
110-
if seen_groups.insert(group_string) {
111-
Some(group_string)
112-
} else {
113-
None
114-
}
115-
})
96+
.map(|v| v.as_str())
11697
.collect::<Vec<&str>>()
11798
.as_slice(),
11899
",",

src/dx/presence/builders/heartbeat.rs

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ pub struct HeartbeatRequest<T, D> {
5656
/// Channel(s) for announcement.
5757
#[builder(
5858
field(vis = "pub(in crate::dx::presence)"),
59-
setter(strip_option, into),
59+
setter(custom, strip_option),
6060
default = "vec![]"
6161
)]
6262
pub(in crate::dx::presence) channels: Vec<String>,
6363

6464
/// Channel group(s) for announcement.
6565
#[builder(
6666
field(vis = "pub(in crate::dx::presence)"),
67-
setter(into, strip_option),
67+
setter(custom, strip_option),
6868
default = "vec![]"
6969
)]
7070
pub(in crate::dx::presence) channel_groups: Vec<String>,
@@ -120,6 +120,69 @@ pub struct HeartbeatRequest<T, D> {
120120
}
121121

122122
impl<T, D> HeartbeatRequestBuilder<T, D> {
123+
/// Channel(s) for announcement.
124+
pub fn channels<L>(mut self, channels: L) -> Self
125+
where
126+
L: Into<Vec<String>>,
127+
{
128+
let mut unique = channels.into();
129+
unique.sort_unstable();
130+
unique.dedup();
131+
132+
self.channels = Some(unique);
133+
self
134+
}
135+
136+
/// Channel group(s) for announcement.
137+
pub fn channel_groups<L>(mut self, channel_groups: L) -> Self
138+
where
139+
L: Into<Vec<String>>,
140+
{
141+
let mut unique = channel_groups.into();
142+
unique.sort_unstable();
143+
unique.dedup();
144+
145+
self.channel_groups = Some(unique);
146+
self
147+
}
148+
149+
/// A state that should be associated with the `user_id`.
150+
///
151+
/// `state` object should be a `HashMap` with channel names as keys and
152+
/// nested `HashMap` with values. State with heartbeat can be set **only**
153+
/// for channels.
154+
///
155+
/// # Example:
156+
/// ```rust,no_run
157+
/// # use std::collections::HashMap;
158+
/// # use pubnub::core::Serialize;
159+
/// # fn main() -> Result<(), pubnub::core::PubNubError> {
160+
/// let state: HashMap<String, HashMap<String, bool>> = HashMap::from([(
161+
/// "announce".to_string(),
162+
/// HashMap::<String, bool>::from([
163+
/// ("is_owner".to_string(), false),
164+
/// ("is_admin".to_string(), true)
165+
/// ])
166+
/// )]);
167+
/// # Ok(())
168+
/// # }
169+
/// ```
170+
pub fn state(mut self, state: HashMap<String, Vec<u8>>) -> Self {
171+
let mut serialized_state = vec![b'{'];
172+
for (key, mut value) in state {
173+
serialized_state.append(&mut format!("\"{}\":", key).as_bytes().to_vec());
174+
serialized_state.append(&mut value);
175+
serialized_state.push(b',');
176+
}
177+
if serialized_state.last() == Some(&b',') {
178+
serialized_state.pop();
179+
}
180+
serialized_state.push(b'}');
181+
182+
self.state = Some(Some(serialized_state));
183+
self
184+
}
185+
123186
/// Validate user-provided data for request builder.
124187
///
125188
/// Validator ensure that provided information is enough to build valid
@@ -184,45 +247,6 @@ impl<T, D> HeartbeatRequest<T, D> {
184247
}
185248
}
186249

187-
impl<T, D> HeartbeatRequestBuilder<T, D> {
188-
/// A state that should be associated with the `user_id`.
189-
///
190-
/// `state` object should be a `HashMap` with channel names as keys and
191-
/// nested `HashMap` with values. State with heartbeat can be set **only**
192-
/// for channels.
193-
///
194-
/// # Example:
195-
/// ```rust,no_run
196-
/// # use std::collections::HashMap;
197-
/// # use pubnub::core::Serialize;
198-
/// # fn main() -> Result<(), pubnub::core::PubNubError> {
199-
/// let state: HashMap<String, HashMap<String, bool>> = HashMap::from([(
200-
/// "announce".to_string(),
201-
/// HashMap::<String, bool>::from([
202-
/// ("is_owner".to_string(), false),
203-
/// ("is_admin".to_string(), true)
204-
/// ])
205-
/// )]);
206-
/// # Ok(())
207-
/// # }
208-
/// ```
209-
pub fn state(mut self, state: HashMap<String, Vec<u8>>) -> Self {
210-
let mut serialized_state = vec![b'{'];
211-
for (key, mut value) in state {
212-
serialized_state.append(&mut format!("\"{}\":", key).as_bytes().to_vec());
213-
serialized_state.append(&mut value);
214-
serialized_state.push(b',');
215-
}
216-
if serialized_state.last() == Some(&b',') {
217-
serialized_state.pop();
218-
}
219-
serialized_state.push(b'}');
220-
221-
self.state = Some(Some(serialized_state));
222-
self
223-
}
224-
}
225-
226250
impl<T, D> HeartbeatRequestBuilder<T, D>
227251
where
228252
T: Transport + 'static,

src/dx/presence/builders/leave.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,18 @@ pub struct LeaveRequest<T, D> {
5353
#[builder(field(vis = "pub(in crate::dx::presence)"), setter(custom))]
5454
pub(in crate::dx::presence) pubnub_client: PubNubClientInstance<T, D>,
5555

56-
/// Channels for announcement.
56+
/// Channel(s) for announcement.
5757
#[builder(
5858
field(vis = "pub(in crate::dx::presence)"),
59-
setter(strip_option, into),
59+
setter(custom, strip_option),
6060
default = "vec![]"
6161
)]
6262
pub(in crate::dx::presence) channels: Vec<String>,
6363

64-
/// Channel groups for announcement.
64+
/// Channel group(s) for announcement.
6565
#[builder(
6666
field(vis = "pub(in crate::dx::presence)"),
67-
setter(into, strip_option),
67+
setter(custom, strip_option),
6868
default = "vec![]"
6969
)]
7070
pub(in crate::dx::presence) channel_groups: Vec<String>,
@@ -76,6 +76,32 @@ pub struct LeaveRequest<T, D> {
7676
}
7777

7878
impl<T, D> LeaveRequestBuilder<T, D> {
79+
/// Channel(s) for announcement.
80+
pub fn channels<L>(mut self, channels: L) -> Self
81+
where
82+
L: Into<Vec<String>>,
83+
{
84+
let mut unique = channels.into();
85+
unique.sort_unstable();
86+
unique.dedup();
87+
88+
self.channels = Some(unique);
89+
self
90+
}
91+
92+
/// Channel group(s) for announcement.
93+
pub fn channel_groups<L>(mut self, channel_groups: L) -> Self
94+
where
95+
L: Into<Vec<String>>,
96+
{
97+
let mut unique = channel_groups.into();
98+
unique.sort_unstable();
99+
unique.dedup();
100+
101+
self.channel_groups = Some(unique);
102+
self
103+
}
104+
79105
/// Validate user-provided data for request builder.
80106
///
81107
/// Validator ensure that list of provided data is enough to build valid

src/dx/pubnub_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ pub struct PubNubClientRef<T, D> {
312312
/// Instance ID
313313
#[builder(
314314
setter(into),
315-
field(ty = "String", build = "Arc::new(Some(Uuid::new_v4().to_string()))")
315+
field(type = "String", build = "Arc::new(Some(Uuid::new_v4().to_string()))")
316316
)]
317317
pub(crate) instance_id: Arc<Option<String>>,
318318

src/dx/subscribe/builders/raw.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,24 @@ pub struct RawSubscription<T, D> {
4848
#[builder(field(vis = "pub(in crate::dx::subscribe)"), setter(custom))]
4949
pub(in crate::dx::subscribe) pubnub_client: PubNubClientInstance<T, D>,
5050

51-
/// Channels from which real-time updates should be received.
51+
/// Channel(s) from which real-time updates should be received.
5252
///
5353
/// List of channels on which [`PubNubClient`] will subscribe and notify
5454
/// about received real-time updates.
5555
#[builder(
5656
field(vis = "pub(in crate::dx::subscribe)"),
57-
setter(into, strip_option),
57+
setter(custom, strip_option),
5858
default = "Vec::new()"
5959
)]
6060
pub(in crate::dx::subscribe) channels: Vec<String>,
6161

62-
/// Channel groups from which real-time updates should be received.
62+
/// Channel group(s) from which real-time updates should be received.
6363
///
6464
/// List of groups of channels on which [`PubNubClient`] will subscribe and
6565
/// notify about received real-time updates.
6666
#[builder(
6767
field(vis = "pub(in crate::dx::subscribe)"),
68-
setter(into, strip_option),
68+
setter(custom, strip_option),
6969
default = "Vec::new()"
7070
)]
7171
pub(in crate::dx::subscribe) channel_groups: Vec<String>,
@@ -110,6 +110,32 @@ pub struct RawSubscription<T, D> {
110110
}
111111

112112
impl<T, D> RawSubscriptionBuilder<T, D> {
113+
/// Channel(s) from which real-time updates should be received.
114+
pub fn channels<L>(mut self, channels: L) -> Self
115+
where
116+
L: Into<Vec<String>>,
117+
{
118+
let mut unique = channels.into();
119+
unique.sort_unstable();
120+
unique.dedup();
121+
122+
self.channels = Some(unique);
123+
self
124+
}
125+
126+
/// Channel group(s) from which real-time updates should be received.
127+
pub fn channel_groups<L>(mut self, channel_groups: L) -> Self
128+
where
129+
L: Into<Vec<String>>,
130+
{
131+
let mut unique = channel_groups.into();
132+
unique.sort_unstable();
133+
unique.dedup();
134+
135+
self.channel_groups = Some(unique);
136+
self
137+
}
138+
113139
/// Validate user-provided data for request builder.
114140
///
115141
/// Validator ensure that list of provided data is enough to build valid
@@ -146,6 +172,7 @@ where
146172
}
147173
}
148174

175+
#[cfg(feature = "blocking")]
149176
impl<T, D> RawSubscriptionBuilder<T, D>
150177
where
151178
T: blocking::Transport,
@@ -226,6 +253,7 @@ where
226253
}
227254
}
228255

256+
#[cfg(feature = "blocking")]
229257
impl<T, D> RawSubscription<T, D>
230258
where
231259
T: blocking::Transport,
@@ -255,6 +283,7 @@ where
255283
}
256284
}
257285

286+
#[cfg(feature = "blocking")]
258287
impl<T, D> Iterator for RawSubscriptionIter<T, D>
259288
where
260289
T: blocking::Transport,

src/dx/subscribe/builders/subscribe.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ pub(crate) struct SubscribeRequest<T, D> {
6060
///
6161
/// List of channels on which [`PubNubClient`] will subscribe and notify
6262
/// about received real-time updates.
63-
#[builder(field(vis = "pub(in crate::dx::subscribe)"), default = "Vec::new()")]
63+
#[builder(
64+
field(vis = "pub(in crate::dx::subscribe)"),
65+
setter(custom, strip_option),
66+
default = "Vec::new()"
67+
)]
6468
pub(in crate::dx::subscribe) channels: Vec<String>,
6569

6670
/// Channel groups from which real-time updates should be received.
@@ -69,7 +73,7 @@ pub(crate) struct SubscribeRequest<T, D> {
6973
/// notify about received real-time updates.
7074
#[builder(
7175
field(vis = "pub(in crate::dx::subscribe)"),
72-
setter(strip_option),
76+
setter(custom, strip_option),
7377
default = "Vec::new()"
7478
)]
7579
pub(in crate::dx::subscribe) channel_groups: Vec<String>,
@@ -143,6 +147,32 @@ pub(crate) struct SubscribeRequest<T, D> {
143147
}
144148

145149
impl<T, D> SubscribeRequestBuilder<T, D> {
150+
/// Channel(s) from which real-time updates should be received.
151+
pub fn channels<L>(mut self, channels: L) -> Self
152+
where
153+
L: Into<Vec<String>>,
154+
{
155+
let mut unique = channels.into();
156+
unique.sort_unstable();
157+
unique.dedup();
158+
159+
self.channels = Some(unique);
160+
self
161+
}
162+
163+
/// Channel group(s) from which real-time updates should be received.
164+
pub fn channel_groups<L>(mut self, channel_groups: L) -> Self
165+
where
166+
L: Into<Vec<String>>,
167+
{
168+
let mut unique = channel_groups.into();
169+
unique.sort_unstable();
170+
unique.dedup();
171+
172+
self.channel_groups = Some(unique);
173+
self
174+
}
175+
146176
/// A state that should be associated with the `user_id`.
147177
///
148178
/// `state` object should be a `HashMap` with channel names as keys and

0 commit comments

Comments
 (0)