1#![cfg_attr(docsrs, feature(doc_auto_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-stock", feature = "zlib-simd", feature = "zstd"))]
21mod compression;
22mod config;
23mod event;
24#[cfg(all(
25 any(feature = "zlib-stock", feature = "zlib-simd"),
26 not(feature = "zstd")
27))]
28mod inflater;
29mod json;
30mod latency;
31mod message;
32mod ratelimiter;
33mod session;
34mod shard;
35mod stream;
36
37#[allow(deprecated)]
38#[cfg(all(
39 any(feature = "zlib-stock", feature = "zlib-simd"),
40 not(feature = "zstd")
41))]
42pub use self::inflater::Inflater;
43pub use self::{
44 channel::MessageSender,
45 command::Command,
46 config::{Config, ConfigBuilder},
47 event::EventTypeFlags,
48 json::parse,
49 latency::Latency,
50 message::Message,
51 ratelimiter::CommandRatelimiter,
52 session::Session,
53 shard::{Shard, ShardState},
54 stream::StreamExt,
55};
56pub use twilight_model::gateway::{CloseFrame, Intents, ShardId};
57
58#[doc(no_inline)]
59pub use twilight_gateway_queue as queue;
60#[doc(no_inline)]
61pub use twilight_model::gateway::event::{Event, EventType};
62
63#[cfg(feature = "twilight-http")]
64use self::error::{StartRecommendedError, StartRecommendedErrorType};
65#[cfg(feature = "twilight-http")]
66use twilight_http::Client;
67
68pub const API_VERSION: u8 = 10;
70
71#[track_caller]
84pub fn create_bucket<F, Q>(
85 bucket_id: u16,
86 concurrency: u16,
87 total: u32,
88 config: Config<Q>,
89 per_shard_config: F,
90) -> impl ExactSizeIterator<Item = Shard<Q>>
91where
92 F: Fn(ShardId, ConfigBuilder<Q>) -> Config<Q>,
93 Q: Clone,
94{
95 assert!(
96 u32::from(bucket_id) < total,
97 "bucket id must be less than the total"
98 );
99 assert!(
100 bucket_id < concurrency,
101 "bucket id must be less than concurrency"
102 );
103 assert!(
104 (u32::from(concurrency)) < total,
105 "concurrency must be less than the total"
106 );
107
108 create_iterator(
109 (u32::from(bucket_id)..total).step_by(concurrency.into()),
110 total,
111 config,
112 per_shard_config,
113 )
114}
115
116#[track_caller]
144pub fn create_iterator<F, Q>(
145 numbers: impl ExactSizeIterator<Item = u32>,
146 total: u32,
147 config: Config<Q>,
148 per_shard_config: F,
149) -> impl ExactSizeIterator<Item = Shard<Q>>
150where
151 F: Fn(ShardId, ConfigBuilder<Q>) -> Config<Q>,
152 Q: Clone,
153{
154 numbers.map(move |index| {
155 let id = ShardId::new(index, total);
156 let config = per_shard_config(id, ConfigBuilder::from(config.clone()));
157
158 Shard::with_config(id, config)
159 })
160}
161
162#[cfg(feature = "twilight-http")]
183pub async fn create_recommended<F, Q>(
184 client: &Client,
185 config: Config<Q>,
186 per_shard_config: F,
187) -> Result<impl ExactSizeIterator<Item = Shard<Q>>, StartRecommendedError>
188where
189 F: Fn(ShardId, ConfigBuilder<Q>) -> Config<Q>,
190 Q: Clone,
191{
192 let request = client.gateway().authed();
193 let response = request.await.map_err(|source| StartRecommendedError {
194 kind: StartRecommendedErrorType::Request,
195 source: Some(Box::new(source)),
196 })?;
197 let info = response
198 .model()
199 .await
200 .map_err(|source| StartRecommendedError {
201 kind: StartRecommendedErrorType::Deserializing,
202 source: Some(Box::new(source)),
203 })?;
204
205 Ok(create_iterator(
206 0..info.shards,
207 info.shards,
208 config,
209 per_shard_config,
210 ))
211}