1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![warn(
4 clippy::missing_const_for_fn,
5 clippy::missing_docs_in_private_items,
6 clippy::pedantic,
7 missing_docs,
8 unsafe_code
9)]
10#![allow(
11 clippy::module_name_repetitions,
12 clippy::must_use_candidate,
13 clippy::unnecessary_wraps
14)]
15
16pub mod error;
17
18mod channel;
19mod command;
20#[cfg(any(feature = "zlib", feature = "zstd"))]
21mod compression;
22mod config;
23mod event;
24mod json;
25mod latency;
26mod message;
27mod ratelimiter;
28mod session;
29mod shard;
30mod stream;
31
32pub use self::{
33 channel::MessageSender,
34 command::Command,
35 config::{Config, ConfigBuilder},
36 event::EventTypeFlags,
37 json::parse,
38 latency::Latency,
39 message::Message,
40 ratelimiter::CommandRatelimiter,
41 session::Session,
42 shard::{Shard, ShardState},
43 stream::StreamExt,
44};
45pub use twilight_model::gateway::{CloseFrame, Intents, ShardId};
46
47#[doc(no_inline)]
48pub use twilight_gateway_queue as queue;
49#[doc(no_inline)]
50pub use twilight_model::gateway::event::{Event, EventType};
51
52#[allow(deprecated)]
53#[cfg(feature = "twilight-http")]
54use self::error::{StartRecommendedError, StartRecommendedErrorType};
55#[cfg(feature = "twilight-http")]
56use twilight_http::Client;
57
58pub const API_VERSION: u8 = 10;
60
61#[inline]
105#[track_caller]
106pub fn bucket(
107 bucket_id: u16,
108 buckets: u16,
109 shards: u32,
110) -> impl DoubleEndedIterator<Item = ShardId> + ExactSizeIterator {
111 let bucket_id = u32::from(bucket_id);
112 let buckets = u32::from(buckets);
113 assert!(bucket_id < buckets, "bucket_id must be less than buckets");
114
115 let (q, r) = (shards / buckets, shards % buckets);
116
117 let len = q + u32::from(bucket_id < r);
118 let start = bucket_id * q + r.min(bucket_id);
119
120 if shards < start + len {
122 std::process::abort();
123 }
124 (start..start + len).map(move |id| ShardId::new(id, shards))
125}
126
127#[deprecated(
140 since = "0.17.2",
141 note = "creates non-consecutive shards; use `bucket` instead"
142)]
143#[track_caller]
144pub fn create_bucket<F, Q>(
145 bucket_id: u16,
146 concurrency: u16,
147 total: u32,
148 config: Config<Q>,
149 per_shard_config: F,
150) -> impl ExactSizeIterator<Item = Shard<Q>>
151where
152 F: FnMut(ShardId, ConfigBuilder<Q>) -> Config<Q>,
153 Q: Clone,
154{
155 assert!(
156 u32::from(bucket_id) < total,
157 "bucket id must be less than the total"
158 );
159 assert!(
160 bucket_id < concurrency,
161 "bucket id must be less than concurrency"
162 );
163 assert!(
164 (u32::from(concurrency)) < total,
165 "concurrency must be less than the total"
166 );
167
168 #[allow(deprecated)]
169 create_iterator(
170 (u32::from(bucket_id)..total).step_by(concurrency.into()),
171 total,
172 config,
173 per_shard_config,
174 )
175}
176
177#[deprecated(since = "0.17.2", note = "use `bucket` instead")]
205#[track_caller]
206pub fn create_iterator<F, Q>(
207 numbers: impl ExactSizeIterator<Item = u32>,
208 total: u32,
209 config: Config<Q>,
210 mut per_shard_config: F,
211) -> impl ExactSizeIterator<Item = Shard<Q>>
212where
213 F: FnMut(ShardId, ConfigBuilder<Q>) -> Config<Q>,
214 Q: Clone,
215{
216 numbers.map(move |index| {
217 let id = ShardId::new(index, total);
218 let config = per_shard_config(id, ConfigBuilder::from(config.clone()));
219
220 Shard::with_config(id, config)
221 })
222}
223
224#[allow(deprecated)]
245#[cfg(feature = "twilight-http")]
246#[deprecated(
247 since = "0.17.2",
248 note = "fetch the recommended shard count via `client.gateway().authed()` instead (from `twilight_http::Client`)"
249)]
250pub async fn create_recommended<F, Q>(
251 client: &Client,
252 config: Config<Q>,
253 per_shard_config: F,
254) -> Result<impl ExactSizeIterator<Item = Shard<Q>> + use<F, Q>, StartRecommendedError>
255where
256 F: FnMut(ShardId, ConfigBuilder<Q>) -> Config<Q>,
257 Q: Clone,
258{
259 let request = client.gateway().authed();
260 let response = request.await.map_err(|source| StartRecommendedError {
261 kind: StartRecommendedErrorType::Request,
262 source: Some(Box::new(source)),
263 })?;
264 let info = response
265 .model()
266 .await
267 .map_err(|source| StartRecommendedError {
268 kind: StartRecommendedErrorType::Deserializing,
269 source: Some(Box::new(source)),
270 })?;
271
272 #[allow(deprecated)]
273 Ok(create_iterator(
274 0..info.shards,
275 info.shards,
276 config,
277 per_shard_config,
278 ))
279}