From fb8ce159d394c4fe06afa6f9b5b7b949b21f6617 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Sun, 13 Apr 2025 00:21:34 -0500 Subject: [PATCH] add cache lmao --- README.md | 1 + build.zig.zon | 5 +- src/cache.zig | 185 +++++++++++++++++++++++++ src/config.zig | 274 ++++++++++++++++++++++++++++++++++++++ src/core.zig | 4 + src/discord.zig | 13 +- src/extra/permissions.zig | 65 +++++++++ src/shard.zig | 3 + test/test.zig | 1 + 9 files changed, 543 insertions(+), 8 deletions(-) create mode 100644 src/cache.zig create mode 100644 src/config.zig create mode 100644 src/extra/permissions.zig diff --git a/README.md b/README.md index 8b8c098..e2c535d 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ pub fn main() !void { .intents = Discord.Intents.fromRaw(53608447), .token = std.posix.getenv("DISCORD_TOKEN").?, .run = .{ .message_create = &message_create, .ready = &ready }, + .cache = Discord.CacheTables, }); } ``` diff --git a/build.zig.zon b/build.zig.zon index ccf1da2..4e94b4b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -28,10 +28,7 @@ .url = "https://github.com/yuzudev/zig-zlib/archive/refs/heads/main.zip", .hash = "zlib-0.1.0-AAAAAKm6QADNBB6NBPHanW9G0EOPTmgJsRO6NFT__arp", }, - .websocket = .{ - .url = "https://github.com/karlseguin/websocket.zig/archive/refs/heads/master.zip", - .hash = "websocket-0.1.0-ZPISdYBIAwB1yO6AFDHRHLaZSmpdh4Bz4dCmaQUqNNWh" - }, + .websocket = .{ .url = "https://github.com/karlseguin/websocket.zig/archive/refs/heads/master.zip", .hash = "websocket-0.1.0-ZPISdYBIAwB1yO6AFDHRHLaZSmpdh4Bz4dCmaQUqNNWh" }, }, .paths = .{ "build.zig", diff --git a/src/cache.zig b/src/cache.zig new file mode 100644 index 0000000..f284e6b --- /dev/null +++ b/src/cache.zig @@ -0,0 +1,185 @@ +const std = @import("std"); + +// by default this caches everything +// therefore we'll allow custom cache tables +pub const CacheTables = struct { + const Snowflake = @import("./structures/snowflake.zig").Snowflake; + const Types = @import("./structures/types.zig"); + + const StoredUser = @import("./config.zig").StoredUser; + const StoredGuild = @import("./config.zig").StoredGuild; + const StoredChannel = @import("./config.zig").StoredChannel; + const StoredEmoji = @import("./config.zig").StoredEmoji; + const StoredMessage = @import("./config.zig").StoredMessage; + const StoredRole = @import("./config.zig").StoredRole; + const StoredSticker = @import("./config.zig").StoredSticker; + const StoredReaction = @import("./config.zig").StoredReaction; + const StoredMember = @import("./config.zig").StoredMember; + + users: CacheLike(Snowflake, StoredUser), + guilds: CacheLike(Snowflake, StoredGuild), + channels: CacheLike(Snowflake, StoredChannel), + emojis: CacheLike(Snowflake, StoredEmoji), + messages: CacheLike(Snowflake, StoredMessage), + roles: CacheLike(Snowflake, StoredRole), + stickers: CacheLike(Snowflake, StoredSticker), + reactions: CacheLike(Snowflake, StoredReaction), + members: CacheLike(Snowflake, StoredMember), + threads: CacheLike(Snowflake, StoredChannel), + + /// you can customize with your own cache + pub fn defaults(allocator: std.mem.Allocator) CacheTables { + var users = DefaultCache(Snowflake, StoredUser).init(allocator); + var guilds = DefaultCache(Snowflake, StoredGuild).init(allocator); + var channels = DefaultCache(Snowflake, StoredChannel).init(allocator); + var emojis = DefaultCache(Snowflake, StoredEmoji).init(allocator); + var messages = DefaultCache(Snowflake, StoredMessage).init(allocator); + var roles = DefaultCache(Snowflake, StoredRole).init(allocator); + var stickers = DefaultCache(Snowflake, StoredSticker).init(allocator); + var reactions = DefaultCache(Snowflake, StoredReaction).init(allocator); + var members = DefaultCache(Snowflake, StoredMember).init(allocator); + var threads = DefaultCache(Snowflake, StoredChannel).init(allocator); + + return .{ + .users = users.cache(), + .guilds = guilds.cache(), + .channels = channels.cache(), + .emojis = emojis.cache(), + .messages = messages.cache(), + .roles = roles.cache(), + .stickers = stickers.cache(), + .reactions = reactions.cache(), + .members = members.cache(), + .threads = threads.cache(), + }; + } +}; + +pub fn CacheLike(comptime K: type, comptime V: type) type { + return struct { + ptr: *anyopaque, + putFn: *const fn(*anyopaque, K, V) anyerror!void, + getFn: *const fn(*anyopaque, K) ?V, + removeFn: *const fn(*anyopaque, K) void, + containsFn: *const fn(*anyopaque, K) bool, + countFn: *const fn(*anyopaque) usize, + + pub fn put(self: CacheLike(K, V), key: K, value: V) !void { + self.putFn(self.ptr, key, value); + } + + pub fn get(self: CacheLike(K, V), key: K) ?V { + return self.getFn(self.ptr, key); + } + + pub fn remove(self: CacheLike(K, V), key: K) void { + self.removeFn(self.ptr, key); + } + + pub fn contains(self: CacheLike(K, V), key: K) bool { + return self.containsFn(self.ptr, key); + } + + pub fn count(self: CacheLike(K, V)) usize { + return self.countFn(self.ptr); + } + + pub fn init(ptr: *const anyopaque) CacheLike(K, V) { + const T = @TypeOf(ptr); + const ptr_info = @typeInfo(T); + + const gen = struct { + // we don't care about order + map: std.AutoHashMap(K, V), + allocator: *std.mem.Allocator, + + pub fn put(pointer: *anyopaque, key: K, value: V) anyerror!void { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.pointer.child.put(self, key, value); + } + + pub fn get(pointer: *anyopaque, key: K) ?V { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.pointer.child.get(self, key); + } + + pub fn remove(pointer: *anyopaque, key: K) void { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.pointer.child.remove(self, key); + } + + pub fn contains(pointer: *anyopaque, key: K) bool { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.pointer.child.contains(self, key); + } + + pub fn count(pointer: *anyopaque) usize { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.pointer.child.count(self); + } + }; + + return .{ + .ptr = ptr, + .putFn = gen.put, + .getFn = gen.get, + .removeFn = gen.remove, + .containsFn = gen.contains, + .countFn = gen.count, + }; + } + }; +} + +// make a cache that uses a hash map +// must have putFn, getFn, removeFn, etc +// must have a cache() function to return the interface + +pub fn DefaultCache(comptime K: type, comptime V: type) type { + return struct { + const Self = @This(); + + allocator: std.mem.Allocator, + map: std.AutoHashMap(K, V), + + pub fn init(allocator: std.mem.Allocator) DefaultCache(K, V) { + return .{ .allocator = allocator, .map = .init(allocator) }; + } + + pub fn cache(self: *Self) CacheLike(K, V) { + return .{ + .ptr = self, + .putFn = put, + .getFn = get, + .removeFn = remove, + .containsFn = contains, + .countFn = count, + }; + } + + pub fn put(ptr: *anyopaque, key: K, value: V) !void { + const self: *Self = @ptrCast(@alignCast(ptr)); + return self.map.put(key, value); + } + + pub fn get(ptr: *anyopaque, key: K) ?V { + const self: *Self = @ptrCast(@alignCast(ptr)); + return self.map.get(key); + } + + pub fn remove(ptr: *anyopaque, key: K) void { + const self: *Self = @ptrCast(@alignCast(ptr)); + _ = self.map.remove(key); + } + + pub fn contains(ptr: *anyopaque, key: K) bool { + const self: *Self = @ptrCast(@alignCast(ptr)); + return self.map.contains(key); + } + + pub fn count(ptr: *anyopaque) usize { + const self: *Self = @ptrCast(@alignCast(ptr)); + return self.map.count(); + } + }; +} diff --git a/src/config.zig b/src/config.zig new file mode 100644 index 0000000..b1531b9 --- /dev/null +++ b/src/config.zig @@ -0,0 +1,274 @@ +// custom file for configurations you might want + +const PremiumTypes = @import("./structures/shared.zig").PremiumTypes; +const Snowflake = @import("./structures/snowflake.zig").Snowflake; +const AvatarDecorationData = @import("./structures/user.zig").AvatarDecorationData; + +/// https://discord.com/developers/docs/resources/user#user-object +/// modify this to your liking +pub const StoredUser = struct { + username: []const u8, + global_name: ?[]const u8 = null, + locale: ?[]const u8 = null, + flags: ?isize = null, + premium_type: ?PremiumTypes = null, + public_flags: ?isize = null, + accent_color: ?isize = null, + id: Snowflake, + discriminator: []const u8, + avatar: ?[]const u8 = null, + bot: ?bool = null, + system: ?bool = null, + mfa_enabled: ?bool = null, + verified: ?bool = null, + email: ?[]const u8 = null, + banner: ?[]const u8 = null, + avatar_decoration_data: ?AvatarDecorationData = null, + clan: ?[]const u8 = null, +}; + +const VerificationLevels = @import("./structures/shared.zig").VerificationLevels; +const DefaultMessageNotificationLevels = @import("./structures/shared.zig").DefaultMessageNotificationLevels; +const ExplicitContentFilterLevels = @import("./structures/shared.zig").ExplicitContentFilterLevels; +const GuildFeatures = @import("./structures/shared.zig").GuildFeatures; +const MfaLevels = @import("./structures/shared.zig").MfaLevels; +const SystemChannelFlags = @import("./structures/shared.zig").SystemChannelFlags; +const PremiumTiers = @import("./structures/shared.zig").PremiumTiers; +const GuildNsfwLevel = @import("./structures/shared.zig").GuildNsfwLevel; +const StageInstance = @import("./structures/channel.zig").StageInstance; +const WelcomeScreen = @import("./structures/channel.zig").WelcomeScreen; + +/// https://discord.com/developers/docs/resources/guild#guild-object +/// modify this to your liking +pub const StoredGuild = struct { + name: []const u8, + widget_enabled: ?bool = null, + verification_level: VerificationLevels, + default_message_notifications: DefaultMessageNotificationLevels, + explicit_content_filter: ExplicitContentFilterLevels, + features: []GuildFeatures, + mfa_level: MfaLevels, + system_channel_flags: SystemChannelFlags, + large: ?bool = null, + unavailable: ?bool = null, + member_count: ?isize = null, + max_presences: ?isize = null, + max_members: ?isize = null, + vanity_url_code: ?[]const u8 = null, + description: ?[]const u8 = null, + premium_tier: PremiumTiers, + premium_subscription_count: ?isize = null, + /// returned from the GET /guilds/id endpoint when with_counts is true + approximate_member_count: ?isize = null, + /// returned from the GET /guilds/id endpoint when with_counts is true + approximate_presence_count: ?isize = null, + nsfw_level: GuildNsfwLevel, + id: Snowflake, + icon: ?[]const u8 = null, + icon_hash: ?[]const u8 = null, + splash: ?[]const u8 = null, + discovery_splash: ?[]const u8 = null, + owner_id: Snowflake, + permissions: ?[]const u8 = null, + afk_channel_id: ?Snowflake = null, + widget_channel_id: ?Snowflake = null, + application_id: ?Snowflake = null, + system_channel_id: ?Snowflake = null, + rules_channel_id: ?Snowflake = null, + banner: ?[]const u8 = null, + preferred_locale: []const u8, + public_updates_channel_id: ?Snowflake = null, + welcome_screen: ?WelcomeScreen = null, + stage_instances: ?[]StageInstance = null, + safety_alerts_channel_id: ?Snowflake = null, +}; + +const ChannelTypes = @import("./structures/shared.zig").ChannelTypes; +const Overwrite = @import("./structures/channel.zig").Overwrite; +const VideoQualityModes = @import("./structures/shared.zig").VideoQualityModes; +const ThreadMetadata = @import("./structures/thread.zig").ThreadMetadata; +const ChannelFlags = @import("./structures/shared.zig").ChannelFlags; +const ForumTag = @import("./structures/channel.zig").ForumTag; +const DefaultReactionEmoji = @import("./structures/channel.zig").DefaultReactionEmoji; +const SortOrderTypes = @import("./structures/shared.zig").SortOrderTypes; +const ForumLayout = @import("./structures/shared.zig").ForumLayout; + +/// https://discord.com/developers/docs/resources/channel#channel-object +/// modify this to your liking +pub const StoredChannel = struct { + id: Snowflake, + type: ChannelTypes, + guild_id: ?Snowflake = null, + position: ?isize = null, + permission_overwrites: ?[]Overwrite = null, + name: ?[]const u8 = null, + topic: ?[]const u8 = null, + nsfw: ?bool = null, + user_limit: ?isize = null, + icon: ?[]const u8 = null, + owner_id: ?Snowflake = null, + application_id: ?Snowflake = null, + managed: ?bool = null, + parent_id: ?Snowflake = null, + last_pin_timestamp: ?[]const u8 = null, + rtc_region: ?[]const u8 = null, + video_quality_mode: ?VideoQualityModes = null, + message_count: ?isize = null, + member_count: ?isize = null, + /// Thread-specific fields not needed by other channels + /// TODO: optimise this + thread_metadata: ?ThreadMetadata = null, + /// threads + default_auto_archive_duration: ?isize = null, + permissions: ?[]const u8 = null, + flags: ?ChannelFlags = null, + total_message_sent: ?isize = null, + /// forum channels + available_tags: ?[]ForumTag = null, + /// forum channels + applied_tags: ?[][]const u8 = null, + /// forum channels + default_reaction_emoji: ?DefaultReactionEmoji = null, + /// threads and channels + default_thread_rate_limit_per_user: ?isize = null, + /// forum channels + default_sort_order: ?SortOrderTypes = null, + /// forum channels + default_forum_layout: ?ForumLayout = null, + /// When a thread is created this will be true on that channel payload for the thread. + /// TODO: optimise this + newly_created: ?bool = null, +}; + + +/// https://discord.com/developers/docs/resources/emoji#emoji-object-emoji-structure +/// modifyus to your liking +pub const StoredEmoji = struct { + name: ?[]const u8 = null, + id: ?Snowflake = null, + roles: ?[][]const u8 = null, + user_id: ?Snowflake = null, + require_colons: ?bool = null, + managed: ?bool = null, + animated: ?bool = null, + available: ?bool = null, +}; + +const MessageTypes = @import("./structures/shared.zig").MessageTypes; +const Attachment = @import("./structures/attachment.zig").Attachment; +const Embed = @import("./structures/embed.zig").Embed; +const ChannelMention = @import("./structures/message.zig").ChannelMention; +const MessageActivity = @import("./structures/message.zig").MessageActivity; +const MessageFlags = @import("./structures/shared.zig").MessageFlags; +const StickerItem = @import("./structures/sticker.zig").StickerItem; +const Poll = @import("./structures/poll.zig").Poll; +const MessageCall = @import("./structures/message.zig").MessageCall; + +/// https://discord.com/developers/docs/resources/channel#message-object +/// modify this to your liking +pub const StoredMessage = struct { + id: Snowflake, + channel_id: Snowflake, + guild_id: ?Snowflake = null, + author_id: Snowflake, + member_id: ?Snowflake = null, + content: ?[]const u8 = null, + timestamp: []const u8, + edited_timestamp: ?[]const u8 = null, + tts: bool, + mention_everyone: bool, + mentions: []Snowflake, + mention_roles: ?[][]const u8 = null, + mention_channels: ?[]ChannelMention = null, + attachments: []Attachment, + embeds: []Embed, + reactions: ?[]Snowflake = null, + // Used for validating a message was sent + // nonce: ?union(enum) {int: isize,string: []const u8,} = null, + pinned: bool, + webhook_id: ?Snowflake = null, + type: MessageTypes, + // interactions or webhooks + application_id: ?Snowflake = null, + // Data showing the source of a crosspost, channel follow add, pin, or reply message + // message_reference: ?Omit(MessageReference, .{"failIfNotExists"}) = null, + flags: ?MessageFlags = null, + referenced_message_id: ?Snowflake = null, + // The thread that was started from this message, includes thread member object + // thread: ?Omit(Channel, .{"member"}), //& { member: ThreadMember }; = null, + components: ?[]Snowflake = null, + sticker_items: ?[]StickerItem = null, + /// threads, may be deleted? + position: ?isize = null, + poll: ?Poll = null, + call: ?MessageCall = null, +}; + +const RoleFlags = @import("./structures/shared.zig").RoleFlags; +const RoleTags = @import("./structures/role.zig").RoleTags; + +/// https://discord.com/developers/docs/topics/permissions#role-object-role-structure +/// modify this to your liking +pub const StoredRole = struct { + id: Snowflake, + hoist: bool, + permissions: []const u8, + managed: bool, + mentionable: bool, + tags: ?RoleTags = null, + icon: ?[]const u8 = null, + name: []const u8, + color: isize, + position: isize, + unicode_emoji: ?[]const u8 = null, + flags: RoleFlags, +}; + +const StickerTypes = @import("./structures/shared.zig").StickerTypes; +const StickerFormatTypes = @import("./structures/shared.zig").StickerFormatTypes; + +/// https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-structure +/// I don't know why you'd cache a sticker, but I deliver what I promise +pub const StoredSticker = struct { + id: Snowflake, + pack_id: ?Snowflake = null, + name: []const u8, + description: []const u8, + tags: []const u8, + type: StickerTypes, + format_type: StickerFormatTypes, + available: ?bool = null, + guild_id: ?Snowflake = null, + user_id: ?Snowflake = null, + sort_value: ?isize = null, +}; + +const ReactionCountDetails = @import("./structures/message.zig").ReactionCountDetails; + +/// https://discord.com/developers/docs/resources/channel#reaction-object +/// This is actually beneficial to cache +pub const StoredReaction = struct { + count: isize, + count_details: ReactionCountDetails, + me: bool, + me_burst: bool, + emoji_id: []const u8, + burst_colors: [][]const u8, +}; + + +/// https://discord.com/developers/docs/resources/guild#guild-member-object +/// modify this to your liking +pub const StoredMember = struct { + pending: ?bool = null, + user_id: ?Snowflake = null, + nick: ?[]const u8 = null, + avatar: ?[]const u8 = null, + roles: [][]const u8, + joined_at: []const u8, + premium_since: ?[]const u8 = null, + permissions: ?[]const u8 = null, + flags: isize, + avatar_decoration_data: ?AvatarDecorationData = null, +}; + diff --git a/src/core.zig b/src/core.zig index 79b9dbb..bb4d51b 100644 --- a/src/core.zig +++ b/src/core.zig @@ -44,6 +44,7 @@ workers: std.Thread.Pool = undefined, /// configuration settings options: SessionOptions, log: Log, +cache: @import("cache.zig").CacheTables, pub const ShardData = struct { /// resume seq to resume connections @@ -80,6 +81,7 @@ pub fn init(allocator: mem.Allocator, settings: struct { options: SessionOptions, run: GatewayDispatchEvent(*Shard), log: Log, + cache: @import("cache.zig").CacheTables, }) mem.Allocator.Error!Self { const concurrency = settings.options.info.session_start_limit.?.max_concurrency; return .{ @@ -104,6 +106,7 @@ pub fn init(allocator: mem.Allocator, settings: struct { .workers_per_shard = settings.options.workers_per_shard, }, .log = settings.log, + .cache = settings.cache, }; } @@ -180,6 +183,7 @@ fn create(self: *Self, shard_id: usize) !Shard { }, .run = self.handler, .log = self.log, + .cache = self.cache, .sharder_pool = &self.workers, }); diff --git a/src/discord.zig b/src/discord.zig index 6375ca9..4e04f96 100644 --- a/src/discord.zig +++ b/src/discord.zig @@ -163,8 +163,6 @@ pub const ModifyGuildChannelPositions = @import("structures/types.zig").ModifyGu pub const CreateChannelInvite = @import("structures/types.zig").CreateChannelInvite; pub const ApplicationCommand = @import("structures/types.zig").ApplicationCommand; pub const CreateApplicationCommand = @import("structures/types.zig").CreateApplicationCommand; -pub const LocaleMap = @import("structures/types.zig").LocaleMap; -pub const InteractionEntryPointCommandHandlerType = @import("structures/types.zig").InteractionEntryPointCommandHandlerType; pub const ApplicationCommandOption = @import("structures/types.zig").ApplicationCommandOption; pub const ApplicationCommandOptionChoice = @import("structures/types.zig").ApplicationCommandOptionChoice; pub const GuildApplicationCommandPermissions = @import("structures/types.zig").GuildApplicationCommandPermissions; @@ -309,8 +307,13 @@ pub const ApplicationWebhook = @import("structures/types.zig").ApplicationWebhoo pub const GatewayPayload = @import("structures/types.zig").GatewayPayload; // END USING NAMESPACE +pub const CacheTables = @import("cache.zig").CacheTables; +pub const CacheLike = @import("cache.zig").CacheLike; +pub const DefaultCache = @import("cache.zig").DefaultCache; + +pub const Permissions = @import("extra/permissions.zig").Permissions; pub const Shard = @import("shard.zig"); -pub const zjson = @compileError("Deprecated, use std.json instead."); +pub const zjson = @compileError("Deprecated."); pub const Internal = @import("internal.zig"); const GatewayDispatchEvent = Internal.GatewayDispatchEvent; @@ -357,6 +360,7 @@ pub fn start(self: *Self, settings: struct { }, run: GatewayDispatchEvent(*Shard), log: Log, + cache: @import("cache.zig").CacheTables, }) !void { self.token = settings.token; var req = FetchReq.init(self.allocator, settings.token); @@ -376,7 +380,7 @@ pub fn start(self: *Self, settings: struct { self.sharder = try Sharder.init(self.allocator, .{ .token = settings.token, - .intents = settings.intents, + .intents = settings.intents, .run = settings.run, .options = SessionOptions{ .info = parsed.value, @@ -386,6 +390,7 @@ pub fn start(self: *Self, settings: struct { .spawn_shard_delay = settings.options.spawn_shard_delay, }, .log = settings.log, + .cache = settings.cache, }); try self.sharder.spawnShards(); diff --git a/src/extra/permissions.zig b/src/extra/permissions.zig new file mode 100644 index 0000000..cc46ec3 --- /dev/null +++ b/src/extra/permissions.zig @@ -0,0 +1,65 @@ +const BitwisePermissionFlags = @import("../structures/shared.zig").BitwisePermissionFlags; + +pub const Permissions = struct { + bitfield: BitwisePermissionFlags = .{}, + + pub fn all() BitwisePermissionFlags { + var bits: @Vector(u64, u1) = @bitCast(BitwisePermissionFlags{}); + + bits = @splat(1); + + return BitwisePermissionFlags.fromRaw(@bitCast(bits)); + } + + pub fn init(bitfield: anytype) Permissions { + return Permissions{ .bitfield = @bitCast(bitfield) }; + } + + pub fn has(self: Permissions, bit: u1) bool { + return (self.bitfield & bit) == bit; + } + + pub fn missing(self: Permissions, bit: u1) bool { + return (self.bitfield & bit) == 0; + } + + pub fn equals(self: Permissions, other: anytype) bool { + return self.bitfield == Permissions.init(other).bitfield; + } + + pub fn add(self: Permissions, bit: u1) void { + self.bitfield |= bit; + } + + pub fn remove(self: Permissions, bit: u1) void { + self.bitfield &= ~bit; + } + + pub fn has2(self: Permissions, bit: u1) bool { + const administrator = BitwisePermissionFlags{ .ADMINISTRATOR = true }; + return self.has(bit) or (self.bitfield & administrator) == administrator; + } + + pub fn toRaw(self: Permissions) u64 { + return @bitCast(self.bitfield); + } + + pub fn fromRaw(raw: u64) Permissions { + return Permissions{ .bitfield = @bitCast(raw) }; + } + /// std.json stringify + pub fn jsonStringify(permissions: Permissions, writer: anytype) !void { + try writer.print("", .{permissions.toRaw()}); + } +}; + +const testing = @import("std").testing; + +test { + const all_permissions = Permissions.all(); + + // 2^40 - 1 = 1099511627775 + const ALL: u64 = 1099511627775; + + testing.expectEqual(all_permissions.toRaw(), ALL); +} diff --git a/src/shard.zig b/src/shard.zig index fd14344..117daa0 100644 --- a/src/shard.zig +++ b/src/shard.zig @@ -99,6 +99,7 @@ inflator: zlib.Decompressor, ws_mutex: std.Thread.Mutex = .{}, rw_mutex: std.Thread.RwLock = .{}, log: Log = .no, +cache: @import("cache.zig").CacheTables, pub fn resumable(self: *Self) bool { return self.resume_gateway_url != null and @@ -152,6 +153,7 @@ pub fn init(allocator: mem.Allocator, shard_id: usize, total_shards: usize, sett options: ShardOptions, run: GatewayDispatchEvent(*Self), log: Log, + cache: @import("cache.zig").CacheTables, sharder_pool: ?*std.Thread.Pool = null, }) zlib.Error!Self { return Self{ @@ -183,6 +185,7 @@ pub fn init(allocator: mem.Allocator, shard_id: usize, total_shards: usize, sett settings.options.ratelimit_options.ratelimit_reset_interval, Self.calculateSafeRequests(settings.options.ratelimit_options), ), + .cache = settings.cache, .sharder_pool = settings.sharder_pool, }; } diff --git a/test/test.zig b/test/test.zig index b26fcb2..3931fb8 100644 --- a/test/test.zig +++ b/test/test.zig @@ -48,5 +48,6 @@ pub fn main() !void { .run = .{ .message_create = &message_create, .ready = &ready }, .log = .yes, .options = .{}, + .cache = Discord.CacheTables.defaults(allocator), }); }