Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental typesize support #2592

Merged
merged 2 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ mime_guess = { version = "2.0.4", optional = true }
dashmap = { version = "5.5.3", features = ["serde"], optional = true }
parking_lot = { version = "0.12.1", optional = true }
ed25519-dalek = { version = "2.0.0", optional = true }
typesize = { version = "0.1.2", optional = true, features = ["url", "time", "serde_json", "secrecy", "dashmap", "parking_lot", "details"] }
# serde feature only allows for serialisation,
# Serenity workspace crates
command_attr = { version = "0.5.0", path = "./command_attr", optional = true }
Expand Down Expand Up @@ -110,16 +111,18 @@ voice = ["client", "model"]
# Enables unstable tokio features to give explicit names to internally spawned tokio tasks
tokio_task_builder = ["tokio/tracing"]
interactions_endpoint = ["ed25519-dalek"]
# Uses chrono for Timestamp, instead of time
chrono = ["dep:chrono", "typesize?/chrono"]

# This enables all parts of the serenity codebase
# (Note: all feature-gated APIs to be documented should have their features listed here!)
full = ["default", "collector", "unstable_discord_api", "voice", "voice_model", "interactions_endpoint"]

# Enables simd accelerated parsing.
simd_json = ["simd-json"]
simd_json = ["simd-json", "typesize?/simd_json"]

# Enables temporary caching in functions that retrieve data via the HTTP API.
temp_cache = ["cache", "mini-moka"]
temp_cache = ["cache", "mini-moka", "typesize?/mini_moka"]

# Removed feature (https://github.com/serenity-rs/serenity/pull/2246)
absolute_ratelimits = []
Expand Down
12 changes: 8 additions & 4 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ mod event;
mod settings;
mod wrappers;

#[cfg(feature = "temp_cache")]
pub(crate) use wrappers::MaybeOwnedArc;
use wrappers::{BuildHasher, MaybeMap, ReadOnlyMapRef};

type MessageCache = DashMap<ChannelId, HashMap<MessageId, Message>, BuildHasher>;
Expand Down Expand Up @@ -75,8 +77,8 @@ impl<'a, K, V, T> CacheRef<'a, K, V, T> {
}

#[cfg(feature = "temp_cache")]
fn from_arc(inner: Arc<V>) -> Self {
Self::new(CacheRefInner::Arc(inner))
fn from_arc(inner: MaybeOwnedArc<V>) -> Self {
Self::new(CacheRefInner::Arc(inner.get_inner()))
}

fn from_ref(inner: Ref<'a, K, V, BuildHasher>) -> Self {
Expand Down Expand Up @@ -120,6 +122,7 @@ pub type GuildChannelsRef<'a> = MappedGuildRef<'a, HashMap<ChannelId, GuildChann
pub type ChannelMessagesRef<'a> = CacheRef<'a, ChannelId, HashMap<MessageId, Message>>;
pub type MessageRef<'a> = CacheRef<'a, ChannelId, Message, HashMap<MessageId, Message>>;

#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Debug)]
pub(crate) struct CachedShardData {
pub total: u32,
Expand All @@ -145,6 +148,7 @@ pub(crate) struct CachedShardData {
///
/// [`Shard`]: crate::gateway::Shard
/// [`http`]: crate::http
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Debug)]
#[non_exhaustive]
pub struct Cache {
Expand All @@ -154,12 +158,12 @@ pub struct Cache {
///
/// The TTL for each value is configured in CacheSettings.
#[cfg(feature = "temp_cache")]
pub(crate) temp_channels: MokaCache<ChannelId, Arc<GuildChannel>, BuildHasher>,
pub(crate) temp_channels: MokaCache<ChannelId, MaybeOwnedArc<GuildChannel>, BuildHasher>,
/// Cache of users who have been fetched from `to_user`.
///
/// The TTL for each value is configured in CacheSettings.
#[cfg(feature = "temp_cache")]
pub(crate) temp_users: MokaCache<UserId, Arc<User>, BuildHasher>,
pub(crate) temp_users: MokaCache<UserId, MaybeOwnedArc<User>, BuildHasher>,

// Channels cache:
/// A map of channel ids to the guilds in which the channel data is stored.
Expand Down
1 change: 1 addition & 0 deletions src/cache/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::time::Duration;
/// let mut settings = CacheSettings::default();
/// settings.max_messages = 10;
/// ```
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Settings {
Expand Down
69 changes: 68 additions & 1 deletion src/cache/wrappers.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
//! Wrappers around library types for easier use.

use std::hash::Hash;
#[cfg(feature = "temp_cache")]
use std::sync::Arc;

use dashmap::mapref::multiple::RefMulti;
use dashmap::mapref::one::{Ref, RefMut};
use dashmap::DashMap;
#[cfg(feature = "typesize")]
use typesize::TypeSize;

#[derive(Debug)]
/// A wrapper around Option<DashMap<K, V>> to ease disabling specific cache fields.
Expand Down Expand Up @@ -49,6 +53,17 @@ impl<K: Eq + Hash, V> MaybeMap<K, V> {
}
}

#[cfg(feature = "typesize")]
impl<K: Eq + Hash + TypeSize, V: TypeSize> TypeSize for MaybeMap<K, V> {
fn extra_size(&self) -> usize {
self.0.as_ref().map(DashMap::extra_size).unwrap_or_default()
}

fn get_collection_item_count(&self) -> Option<usize> {
self.0.as_ref().and_then(DashMap::get_collection_item_count)
}
}

#[derive(Clone, Copy, Debug)]
/// A wrapper around a reference to a MaybeMap, allowing for public inspection of the underlying
/// map without allowing mutation of internal cache fields, which could cause issues.
Expand All @@ -66,7 +81,6 @@ impl<'a, K: Eq + Hash, V> ReadOnlyMapRef<'a, K, V> {
self.0.map_or(0, DashMap::len)
}
}

pub struct Hasher(fxhash::FxHasher);
impl std::hash::Hasher for Hasher {
fn finish(&self) -> u64 {
Expand All @@ -86,3 +100,56 @@ impl std::hash::BuildHasher for BuildHasher {
Hasher(self.0.build_hasher())
}
}

/// Wrapper around `SizableArc<T, Owned>`` with support for disabling typesize.
///
/// This denotes an Arc where T's size should be considered when calling `TypeSize::get_size`
#[derive(Debug)]
#[cfg(feature = "temp_cache")]
pub(crate) struct MaybeOwnedArc<T>(
#[cfg(feature = "typesize")] typesize::ptr::SizableArc<T, typesize::ptr::Owned>,
#[cfg(not(feature = "typesize"))] Arc<T>,
);

#[cfg(feature = "temp_cache")]
impl<T> MaybeOwnedArc<T> {
pub(crate) fn new(inner: T) -> Self {
Self(Arc::new(inner).into())
}

pub(crate) fn get_inner(self) -> Arc<T> {
#[cfg(feature = "typesize")]
let inner = self.0 .0;
#[cfg(not(feature = "typesize"))]
let inner = self.0;

inner
}
}

#[cfg(all(feature = "typesize", feature = "temp_cache"))]
impl<T: typesize::TypeSize> typesize::TypeSize for MaybeOwnedArc<T> {
fn extra_size(&self) -> usize {
self.0.extra_size()
}

fn get_collection_item_count(&self) -> Option<usize> {
self.0.get_collection_item_count()
}
}

#[cfg(feature = "temp_cache")]
impl<T> std::ops::Deref for MaybeOwnedArc<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[cfg(feature = "temp_cache")]
impl<T> Clone for MaybeOwnedArc<T> {
fn clone(&self) -> Self {
Self(self.0.clone().into())
}
}
7 changes: 4 additions & 3 deletions src/internal/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,11 @@ macro_rules! bitflags {
)*
}
) => {
$(#[$outer])*
$vis struct $BitFlags($T);

bitflags::bitflags! {
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
GnomedDev marked this conversation as resolved.
Show resolved Hide resolved
$(#[$outer])*
$vis struct $BitFlags: $T {
impl $BitFlags: $T {
GnomedDev marked this conversation as resolved.
Show resolved Hide resolved
$(
$(#[$inner $($args)*])*
const $Flag = $value;
Expand Down
8 changes: 8 additions & 0 deletions src/model/application/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::model::Permissions;
/// The base command model that belongs to an application.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct Command {
Expand Down Expand Up @@ -222,6 +223,7 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandType {
Expand All @@ -235,6 +237,7 @@ enum_number! {
/// The parameters for an [`Command`].
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandOption {
Expand Down Expand Up @@ -296,6 +299,7 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandOptionType {
Expand All @@ -317,6 +321,7 @@ enum_number! {
/// The only valid values a user can pick in an [`CommandOption`].
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandOptionChoice {
Expand All @@ -332,6 +337,7 @@ pub struct CommandOptionChoice {
/// An [`Command`] permission.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-guild-application-command-permissions-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandPermissions {
Expand All @@ -348,6 +354,7 @@ pub struct CommandPermissions {
/// The [`CommandPermission`] data.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permissions-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandPermission {
Expand All @@ -365,6 +372,7 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permission-type).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandPermissionType {
Expand Down
5 changes: 5 additions & 0 deletions src/model/application/command_interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use crate::utils::{CreateQuickModal, QuickModalResponse};
/// An interaction when a user invokes a slash command.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(remote = "Self")]
#[non_exhaustive]
Expand Down Expand Up @@ -265,6 +266,7 @@ impl Serialize for CommandInteraction {
/// The command data payload.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandData {
Expand Down Expand Up @@ -476,6 +478,7 @@ pub enum ResolvedTarget<'a> {
/// [`CommandDataOption`]s.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-resolved-data-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CommandDataResolved {
Expand Down Expand Up @@ -508,6 +511,7 @@ pub struct CommandDataResolved {
/// Their resolved objects can be found on [`CommandData::resolved`].
///
/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-application-command-interaction-data-option-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct CommandDataOption {
Expand Down Expand Up @@ -632,6 +636,7 @@ impl Serialize for CommandDataOption {
/// The value of an [`CommandDataOption`].
///
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub enum CommandDataOptionValue {
Expand Down
10 changes: 10 additions & 0 deletions src/model/application/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::model::utils::{default_true, deserialize_val};
enum_number! {
/// The type of a component
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ComponentType {
Expand All @@ -27,6 +28,7 @@ enum_number! {
/// An action row.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#action-rows).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ActionRow {
Expand All @@ -41,6 +43,7 @@ pub struct ActionRow {
/// A component which can be inside of an [`ActionRow`].
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#component-object-component-types).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum ActionRowComponent {
Expand Down Expand Up @@ -97,6 +100,7 @@ impl From<SelectMenu> for ActionRowComponent {
}
}

#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum ButtonKind {
Expand Down Expand Up @@ -142,6 +146,7 @@ impl Serialize for ButtonKind {
/// A button component.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#button-object-button-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct Button {
Expand All @@ -165,6 +170,7 @@ pub struct Button {
enum_number! {
/// The style of a button.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ButtonStyle {
Expand All @@ -180,6 +186,7 @@ enum_number! {
/// A select menu component.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct SelectMenu {
Expand Down Expand Up @@ -212,6 +219,7 @@ pub struct SelectMenu {
/// A select menu component options.
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct SelectMenuOption {
Expand All @@ -231,6 +239,7 @@ pub struct SelectMenuOption {
/// An input text component for modal interactions
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#text-inputs-text-input-structure).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[non_exhaustive]
pub struct InputText {
Expand Down Expand Up @@ -275,6 +284,7 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#text-inputs-text-input-styles).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum InputTextStyle {
Expand Down
Loading