From c67291575b800f0c902b7ba04d26c1b804331f0b Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Mon, 2 Oct 2023 18:05:48 -0400 Subject: [PATCH 01/11] improv: freshen up dpp::snowflake and dpp::managed --- include/dpp/managed.h | 42 +++++++++++++-- include/dpp/snowflake.h | 113 ++++++++++++++++------------------------ src/dpp/managed.cpp | 41 --------------- src/dpp/snowflake.cpp | 62 +++------------------- src/unittest/test.cpp | 22 ++++++-- src/unittest/test.h | 1 + 6 files changed, 111 insertions(+), 170 deletions(-) delete mode 100644 src/dpp/managed.cpp diff --git a/include/dpp/managed.h b/include/dpp/managed.h index 5e79953517..612fcd0a64 100644 --- a/include/dpp/managed.h +++ b/include/dpp/managed.h @@ -37,23 +37,53 @@ namespace dpp { * Only the timestamp is relevant to us as useful metadata. */ snowflake id; + /** * @brief Constructor, initialises ID * @param nid ID to set */ - managed(const snowflake nid = 0); + constexpr managed(const snowflake nid = 0) noexcept : id{nid} {} + + /** + * @brief Copy constructor + * @param rhs Object to copy + */ + constexpr managed(const managed &rhs) noexcept = default; + + /** + * @brief Move constructor + * + * Effectively equivalent to copy constructor + * @param rhs Object to move from + */ + constexpr managed(managed &&rhs) noexcept = default; + /** * @brief Destroy the managed object */ virtual ~managed() = default; + /** + * @brief Copy assignment operator + * @param rhs Object to copy + */ + constexpr managed &operator=(const managed& rhs) = default; + + /** + * @brief Move assignment operator + * @param rhs Object to copy + */ + constexpr managed &operator=(managed&& rhs) = default; + /** * @brief Get the creation time of this object according to Discord. * * @return double creation time inferred from the snowflake ID. * The minimum possible value is the first second of 2015. */ - double get_creation_time() const; + constexpr double get_creation_time() const noexcept { + return id.get_creation_time(); + }; /** * @brief Comparison operator for comparing two managed objects by id @@ -62,7 +92,9 @@ namespace dpp { * @return true objects are the same id * @return false objects are not the same id */ - bool operator==(const managed& other) const noexcept; + constexpr bool operator==(const managed& other) const noexcept { + return id == other.id; + } /** * @brief Comparison operator for comparing two managed objects by id @@ -71,7 +103,9 @@ namespace dpp { * @return true objects are not the same id * @return false objects are the same id */ - bool operator!=(const managed& other) const noexcept; + constexpr bool operator!=(const managed& other) const noexcept { + return id != other.id; + } }; } // namespace dpp diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index df223f3f2a..dd6cb8a4d9 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -52,105 +52,75 @@ class DPP_EXPORT snowflake final { /** * @brief The snowflake value */ - uint64_t value; + uint64_t value = 0; public: + /** + * @brief Construct a snowflake object + */ + constexpr snowflake() noexcept = default; + /** * @brief Construct a snowflake object * @param value A snowflake value */ - snowflake(const uint64_t& value); + constexpr snowflake(const uint64_t value_) noexcept : value{value_} {} /** * @brief Construct a snowflake object * @param string_value A snowflake value */ - snowflake(const std::string& string_value); - - /** - * @brief Construct a snowflake object - */ - snowflake(); - - /** - * @brief Destroy the snowflake object - */ - ~snowflake() = default; + snowflake(std::string_view string_value) noexcept; /** * @brief For acting like an integer * @return The snowflake value */ - operator uint64_t() const; + constexpr operator uint64_t() const noexcept { + return value; + } /** * @brief Returns true if the snowflake holds an empty value (is 0) - * + * * @return true if empty (zero) */ - inline bool empty() const - { + constexpr bool empty() const noexcept { return value == 0; } /** * @brief Returns the stringified version of the snowflake value - * + * * @return std::string string form of snowflake value */ - inline std::string str() const - { + inline std::string str() const { return std::to_string(value); } - /** - * @brief Operator less than, used for maps/unordered maps - * when the snowflake is a key value. - * - * @param lhs fist snowflake to compare - * @param rhs second snowflake to compare - * @return true if lhs is less than rhs - */ - friend inline bool operator< (const snowflake& lhs, const snowflake& rhs) - { - return lhs.value < rhs.value; - } - /** * @brief Assign from std::string - * + * * @param snowflake_val string to assign from. */ - snowflake& operator=(const std::string &snowflake_val); - - /** - * @brief Assign from std::string - * - * @param snowflake_val value to assign from. - */ - snowflake& operator=(const uint64_t &snowflake_val); - - /** - * @brief Check if one snowflake value is equal to another - * - * @param other other snowflake to compare - * @return True if the snowflake objects match - */ - bool operator==(const snowflake& other) const; + snowflake& operator=(std::string_view snowflake_val) noexcept; /** - * @brief Check if one snowflake value is equal to a uint64_t - * - * @param other other snowflake to compare - * @return True if the snowflake objects match + * @brief Comparison operator with a string + * + * @param snowflake_val snowflake value as a string */ - bool operator==(const uint64_t& other) const; + inline bool operator==(std::string_view snowflake_val) const noexcept { + return *this == dpp::snowflake{snowflake_val}; + } /** * @brief For acting like an integer * @return A reference to the snowflake value */ - operator uint64_t &(); + constexpr operator uint64_t &() noexcept { + return value; + } /** * @brief For building json @@ -160,33 +130,42 @@ class DPP_EXPORT snowflake final { /** * @brief Get the creation time of this snowflake according to Discord. - * + * * @return double creation time inferred from the snowflake ID. * The minimum possible value is the first second of 2015. */ - double get_creation_time() const; + constexpr double get_creation_time() const noexcept { + constexpr uint64_t first_january_2016 = 1420070400000ull; + return static_cast((value >> 22) + first_january_2016) / 1000.0; + } /** * @brief Get the worker id that produced this snowflake value - * + * * @return uint8_t worker id */ - uint8_t get_worker_id() const; + constexpr uint8_t get_worker_id() const noexcept { + return static_cast((value & 0x3E0000) >> 17); + } /** * @brief Get the process id that produced this snowflake value - * + * * @return uint8_t process id */ - uint8_t get_process_id() const; + constexpr uint8_t get_process_id() const noexcept { + return static_cast((value & 0x1F000) >> 12); + } /** * @brief Get the increment, which is incremented for every snowflake * created over the one millisecond resolution in the timestamp. - * + * * @return uint64_t millisecond increment */ - uint16_t get_increment() const; + constexpr uint16_t get_increment() const noexcept { + return static_cast(value & 0xFFF); + } }; } // namespace dpp @@ -195,13 +174,13 @@ template<> struct std::hash { /** - * @brief Hashing function for dpp::slowflake + * @brief Hashing function for dpp::snowflake * Used by std::unordered_map. This just calls std::hash. - * + * * @param s Snowflake value to hash * @return std::size_t hash value */ - std::size_t operator()(dpp::snowflake const& s) const noexcept { + std::size_t operator()(dpp::snowflake s) const noexcept { return std::hash{}(s.value); } }; diff --git a/src/dpp/managed.cpp b/src/dpp/managed.cpp deleted file mode 100644 index 2a9d8fb1cb..0000000000 --- a/src/dpp/managed.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/************************************************************************************ - * - * D++, A Lightweight C++ library for Discord - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright 2021 Craig Edwards and D++ contributors - * (https://github.com/brainboxdotcc/DPP/graphs/contributors) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ************************************************************************************/ -#include - -namespace dpp { - -managed::managed(const snowflake nid) : id(nid) { -} - -bool managed::operator==(const managed& other) const noexcept { - return id == other.id; -} - -bool managed::operator!=(const managed& other) const noexcept { - return id != other.id; -} - -double managed::get_creation_time() const { - return this->id.get_creation_time(); -} - -} // namespace dpp diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 788ee02481..97d2f9194b 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -19,74 +19,26 @@ * ************************************************************************************/ #include -#include +#include namespace dpp { -snowflake::snowflake(const uint64_t &value) : value(value) {} - -snowflake::snowflake(const std::string &string_value) { - try { - value = std::stoull(string_value); - } - catch (const std::exception &) { +snowflake::snowflake(std::string_view string_value) noexcept { + auto [end, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); + if (end != string_value.data() + string_value.size()) value = 0; - } -} - -snowflake::snowflake() : snowflake(0) {} - -snowflake::operator uint64_t() const { - return value; -} - -snowflake::operator uint64_t &() { - return value; } -snowflake& snowflake::operator=(const std::string &snowflake_val) { - try { - value = std::stoull(snowflake_val); - } - catch (const std::exception &) { +snowflake& snowflake::operator=(std::string_view string_value) { + auto [end, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); + if (end != string_value.data() + string_value.size()) value = 0; - } return *this; } -snowflake& snowflake::operator=(const uint64_t &snowflake_val) { - value = snowflake_val; - return *this; -} - -bool snowflake::operator==(const snowflake& other) const { - return other.value == value; -} - -bool snowflake::operator==(const uint64_t& other) const { - return other == value; -} - snowflake::operator nlohmann::json() const { /* Discord transfers snowflakes as strings for compatibility with javascript */ return std::to_string(value); } -double snowflake::get_creation_time() const { - const uint64_t first_january_2016 = 1420070400000; - return (double)((value >> 22) + first_january_2016) / 1000.0; -} - -uint8_t snowflake::get_worker_id() const { - return (uint8_t)((value & 0x3E0000) >> 17); -} - -uint8_t snowflake::get_process_id() const { - return (uint8_t)((value & 0x1F000) >> 12); -} - -uint16_t snowflake::get_increment() const { - return (value & 0xFFF); -} - } // namespace dpp diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 8173c6842c..ef5caa68e7 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -19,6 +19,7 @@ * limitations under the License. * ************************************************************************************/ +#define DPP_STATIC_TEST #include "test.h" #include #include @@ -193,6 +194,24 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b set_test(WEBHOOK, false); } + { // test dpp::snowflake + bool success = true; + dpp::snowflake s = 69420; + json j; + j["value"] = 69420; + success = dpp::snowflake_not_null(&j, "value") == 69420 && success; + DPP_CHECK_CONSTRUCT_ASSIGN(SNOWFLAKE, dpp::snowflake, success); + s = 42069; + success = success && (s == 42069 && s == dpp::snowflake{42069} && s == "42069"); + success = success && (dpp::snowflake{69} < dpp::snowflake{420} && (dpp::snowflake{69} < 420)); + s = "69420"; + success = success && s == 69420; + s = dpp::snowflake{"1337"}; + success = success && s == 1337; + set_test(SNOWFLAKE, success); + } + + { // test interaction_create_t::get_parameter // create a fake interaction dpp::cluster cluster(""); @@ -299,9 +318,6 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b success = p == 5120 && success; auto s = std::to_string(p); success = s == "5120" && success; - json j; - j["value"] = p; - success = dpp::snowflake_not_null(&j, "value") == 5120 && success; p.set(0).add(~uint64_t{0}).remove(dpp::p_speak).set(dpp::p_administrator); success = !p.has(dpp::p_administrator, dpp::p_ban_members) && success; // must return false because they're not both set success = !p.has(dpp::p_administrator | dpp::p_ban_members) && success; diff --git a/src/unittest/test.h b/src/unittest/test.h index c3b295ae45..3b2a09147c 100644 --- a/src/unittest/test.h +++ b/src/unittest/test.h @@ -80,6 +80,7 @@ struct test_t { #define DPP_TEST(name, desc, flags) inline test_t name = {#name, desc, flags} /* Current list of unit tests */ +DPP_TEST(SNOWFLAKE, "dpp::snowflake class", tf_offline); DPP_TEST(CLUSTER, "Instantiate DPP cluster", tf_offline); DPP_TEST(BOTSTART, "cluster::start method", tf_online); DPP_TEST(CONNECTION, "Connection to client websocket", tf_online); From 734611a139d8cfb17aecedee189a7bc2efa215df Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:08:52 -0400 Subject: [PATCH 02/11] Update test.cpp --- src/unittest/test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index ef5caa68e7..8e55c3cf70 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -19,7 +19,6 @@ * limitations under the License. * ************************************************************************************/ -#define DPP_STATIC_TEST #include "test.h" #include #include From 8cd7aacb61e412fba3e8a4d9c67fb97385501943 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Tue, 3 Oct 2023 10:03:46 -0400 Subject: [PATCH 03/11] more stuff --- include/dpp/managed.h | 9 +++- include/dpp/snowflake.h | 103 +++++++++++++++++++++++++++++++++++----- src/dpp/snowflake.cpp | 3 +- src/unittest/test.cpp | 4 +- 4 files changed, 102 insertions(+), 17 deletions(-) diff --git a/include/dpp/managed.h b/include/dpp/managed.h index 612fcd0a64..84fdfc9c83 100644 --- a/include/dpp/managed.h +++ b/include/dpp/managed.h @@ -36,13 +36,18 @@ namespace dpp { * This value contains a timestamp, worker ID, internal server ID, and an incrementing value. * Only the timestamp is relevant to us as useful metadata. */ - snowflake id; + snowflake id = 0; + + /** + * @brief Constructor, initialises id to 0. + */ + constexpr managed() noexcept = default; /** * @brief Constructor, initialises ID * @param nid ID to set */ - constexpr managed(const snowflake nid = 0) noexcept : id{nid} {} + constexpr managed(const snowflake nid) noexcept : id{nid} {} /** * @brief Copy constructor diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index dd6cb8a4d9..b0336defe4 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -22,8 +22,8 @@ #pragma once #include #include -#include -#include +#include +#include /** * @brief The main namespace for D++ functions. classes and types @@ -61,23 +61,75 @@ class DPP_EXPORT snowflake final { constexpr snowflake() noexcept = default; /** - * @brief Construct a snowflake object - * @param value A snowflake value + * @brief Copy a snowflake object + */ + constexpr snowflake(const snowflake &rhs) noexcept = default; + + /** + * @brief Move a snowflake object + */ + constexpr snowflake(snowflake &&rhs) noexcept = default; + + /** + * @brief Construct a snowflake from an integer value + * + * @throw dpp::logic_exception on assigning a negative value. the function is noexcept if the type given is unsigned + * @param snowflake_val snowflake value as an integer type */ - constexpr snowflake(const uint64_t value_) noexcept : value{value_} {} + template >> + constexpr snowflake(T snowflake_val) noexcept(std::is_unsigned_v) : value(static_cast>(snowflake_val)) { + /** + * we cast to the unsigned version of the type given - this maintains "possible loss of data" warnings for sizeof(T) > sizeof(value) + * while suppressing them for signed to unsigned conversion + */ + if constexpr (!std::is_unsigned_v) { + /* if the type is signed, at compile-time, add a check at runtime that the value is unsigned */ + if (snowflake_val < 0) { + value = 0; + throw dpp::logic_exception{"cannot assign a negative value to dpp::snowflake"}; + } + } + } /** - * @brief Construct a snowflake object + * @brief Construct a snowflake object from an unsigned integer in a string + * + * On invalid string the value will be 0 * @param string_value A snowflake value */ snowflake(std::string_view string_value) noexcept; /** - * @brief For acting like an integer - * @return The snowflake value + * @brief Copy value from another snowflake + * + * @param rhs The snowflake to copy from */ - constexpr operator uint64_t() const noexcept { - return value; + constexpr dpp::snowflake &operator=(const dpp::snowflake& rhs) noexcept = default; + + /** + * @brief Move value from another snowflake + * + * @param rhs The snowflake to move from + */ + constexpr dpp::snowflake &operator=(dpp::snowflake&& rhs) noexcept = default; + + /** + * @brief Assign value converted from a string to the snowflake + * + * On invalid string the value will be 0 + * @param snowflake_val snowflake value as a string + */ + dpp::snowflake &operator=(std::string_view snowflake_val) noexcept; + + /** + * @brief Assign integer value to the snowflake + * + * @throw dpp::logic_exception on assigning a negative value. the function is noexcept if the type given is unsigned + * @param snowflake_val snowflake value as an integer type + */ + template >> + constexpr dpp::snowflake &operator=(T snowflake_val) noexcept(std::is_unsigned_v) { + return *this = dpp::snowflake{snowflake_val}; } /** @@ -99,11 +151,13 @@ class DPP_EXPORT snowflake final { } /** - * @brief Assign from std::string + * @brief Comparison operator with another snowflake * - * @param snowflake_val string to assign from. + * @param snowflake_val snowflake */ - snowflake& operator=(std::string_view snowflake_val) noexcept; + constexpr bool operator==(dpp::snowflake snowflake_val) const noexcept { + return value == snowflake_val.value; + } /** * @brief Comparison operator with a string @@ -111,9 +165,32 @@ class DPP_EXPORT snowflake final { * @param snowflake_val snowflake value as a string */ inline bool operator==(std::string_view snowflake_val) const noexcept { + uint64_t v; + auto [end, err] = std::from_chars(snowflake_val.data(), snowflake_val.data() + snowflake_val.size(), v); + if (end != snowflake_val.data() + snowflake_val.size()) // parse error + return false; + return *this == v; + } + + /** + * @brief Comparison operator with an integer + * + * @param snowflake_val snowflake value as an integer type + */ + template >> + constexpr bool operator==(T snowflake_val) const noexcept { + /* We use the std::enable_if_t trick to disable implicit conversions so there is a perfect candidate for overload resolution for integers, and it isn't ambiguous */ return *this == dpp::snowflake{snowflake_val}; } + /** + * @brief For acting like an integer + * @return The snowflake value + */ + constexpr operator uint64_t() const noexcept { + return value; + } + /** * @brief For acting like an integer * @return A reference to the snowflake value diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 97d2f9194b..46df8583b4 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -20,6 +20,7 @@ ************************************************************************************/ #include #include +#include namespace dpp { @@ -29,7 +30,7 @@ snowflake::snowflake(std::string_view string_value) noexcept { value = 0; } -snowflake& snowflake::operator=(std::string_view string_value) { +snowflake& snowflake::operator=(std::string_view string_value) noexcept { auto [end, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); if (end != string_value.data() + string_value.size()) value = 0; diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 8e55c3cf70..2764dd54ff 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -194,10 +194,11 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b } { // test dpp::snowflake + start_test(SNOWFLAKE); bool success = true; dpp::snowflake s = 69420; json j; - j["value"] = 69420; + j["value"] = s; success = dpp::snowflake_not_null(&j, "value") == 69420 && success; DPP_CHECK_CONSTRUCT_ASSIGN(SNOWFLAKE, dpp::snowflake, success); s = 42069; @@ -207,6 +208,7 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b success = success && s == 69420; s = dpp::snowflake{"1337"}; success = success && s == 1337; + success = success && dpp::snowflake{0} == 0; set_test(SNOWFLAKE, success); } From 1ece72f1d8ea087177be5398c69eadcd439397e6 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Tue, 3 Oct 2023 10:05:40 -0400 Subject: [PATCH 04/11] fixeroni --- include/dpp/snowflake.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index b0336defe4..727728440f 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -22,6 +22,7 @@ #pragma once #include #include +#include #include #include From a64bf370b6795a2831a3b0f802f497eb0ba70fd8 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Tue, 3 Oct 2023 10:09:23 -0400 Subject: [PATCH 05/11] pepperoni? --- include/dpp/managed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dpp/managed.h b/include/dpp/managed.h index 84fdfc9c83..191910b639 100644 --- a/include/dpp/managed.h +++ b/include/dpp/managed.h @@ -36,7 +36,7 @@ namespace dpp { * This value contains a timestamp, worker ID, internal server ID, and an incrementing value. * Only the timestamp is relevant to us as useful metadata. */ - snowflake id = 0; + snowflake id = {}; /** * @brief Constructor, initialises id to 0. From 237c7d60bbc299e247a01c60e48e40d160631e46 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Tue, 3 Oct 2023 10:29:39 -0400 Subject: [PATCH 06/11] macaroni --- include/dpp/cluster.h | 2 -- include/dpp/discordclient.h | 2 -- include/dpp/discordvoiceclient.h | 2 -- include/dpp/event_router.h | 2 -- include/dpp/json.h | 6 +++++- include/dpp/json_fwd.h | 6 +++++- include/dpp/restresults.h | 2 -- include/dpp/snowflake.h | 13 +++++++------ src/dpp/snowflake.cpp | 3 ++- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 55d8bc6b8f..e59331ad76 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -51,8 +51,6 @@ namespace dpp { -using json = nlohmann::json; - /** * @brief Types of startup for cluster::start() */ diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index 08f6ed0d57..ff2f7736f7 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -41,8 +41,6 @@ #define API_PATH "/api/v" DISCORD_API_VERSION namespace dpp { -using json = nlohmann::json; - // Forward declarations class cluster; diff --git a/include/dpp/discordvoiceclient.h b/include/dpp/discordvoiceclient.h index af0e2c5f2f..cc88ec04b8 100644 --- a/include/dpp/discordvoiceclient.h +++ b/include/dpp/discordvoiceclient.h @@ -64,8 +64,6 @@ class audio_mixer; inline constexpr size_t send_audio_raw_max_length = 11520; -using json = nlohmann::json; - /* * @brief For holding a moving average of the number of current voice users, for applying a smooth gain ramp. */ diff --git a/include/dpp/event_router.h b/include/dpp/event_router.h index f6dd3b4664..f759570465 100644 --- a/include/dpp/event_router.h +++ b/include/dpp/event_router.h @@ -36,8 +36,6 @@ #include #include -using json = nlohmann::json; - namespace dpp { #ifdef DPP_CORO diff --git a/include/dpp/json.h b/include/dpp/json.h index fc47bb45f8..bfbf3bebf9 100644 --- a/include/dpp/json.h +++ b/include/dpp/json.h @@ -23,4 +23,8 @@ #include #else #include -#endif \ No newline at end of file +#endif + +namespace dpp { + using json = nlohmann::json; +} diff --git a/include/dpp/json_fwd.h b/include/dpp/json_fwd.h index 75326193ef..e5d8870ea8 100644 --- a/include/dpp/json_fwd.h +++ b/include/dpp/json_fwd.h @@ -23,4 +23,8 @@ #include #else #include -#endif \ No newline at end of file +#endif + +namespace dpp { + using json = nlohmann::json; +} diff --git a/include/dpp/restresults.h b/include/dpp/restresults.h index 0691b41869..5661a596d5 100644 --- a/include/dpp/restresults.h +++ b/include/dpp/restresults.h @@ -44,8 +44,6 @@ #include #include -using json = nlohmann::json; - namespace dpp { #ifdef _WIN32 diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index 727728440f..226a8d88a9 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -25,6 +25,7 @@ #include #include #include +#include /** * @brief The main namespace for D++ functions. classes and types @@ -33,17 +34,17 @@ namespace dpp { /** @brief A container for a 64 bit unsigned value representing many things on discord. * This value is known in distributed computing as a snowflake value. - * + * * Snowflakes are: - * + * * - Performant (very fast to generate at source and to compare in code) * - Uncoordinated (allowing high availability across clusters, data centres etc) * - Time ordered (newer snowflakes have higher IDs) * - Directly Sortable (due to time ordering) * - Compact (64 bit numbers, not 128 bit, or string) - * + * * An identical format of snowflake is used by Twitter, Instagram and several other platforms. - * + * * @see https://en.wikipedia.org/wiki/Snowflake_ID * @see https://github.com/twitter-archive/snowflake/tree/b3f6a3c6ca8e1b6847baa6ff42bf72201e2c2231 */ @@ -81,7 +82,7 @@ class DPP_EXPORT snowflake final { constexpr snowflake(T snowflake_val) noexcept(std::is_unsigned_v) : value(static_cast>(snowflake_val)) { /** * we cast to the unsigned version of the type given - this maintains "possible loss of data" warnings for sizeof(T) > sizeof(value) - * while suppressing them for signed to unsigned conversion + * while suppressing them for signed to unsigned conversion (for example snowflake(42) will call snowflake(int) which is a signed type) */ if constexpr (!std::is_unsigned_v) { /* if the type is signed, at compile-time, add a check at runtime that the value is unsigned */ @@ -204,7 +205,7 @@ class DPP_EXPORT snowflake final { * @brief For building json * @return The snowflake value as a string */ - operator nlohmann::json() const; + operator json() const; /** * @brief Get the creation time of this snowflake according to Discord. diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 46df8583b4..5f7ad6e844 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -19,6 +19,7 @@ * ************************************************************************************/ #include +#include #include #include @@ -37,7 +38,7 @@ snowflake& snowflake::operator=(std::string_view string_value) noexcept { return *this; } -snowflake::operator nlohmann::json() const { +snowflake::operator json() const { /* Discord transfers snowflakes as strings for compatibility with javascript */ return std::to_string(value); } From 111f3b490edd0b89ff844fe6c11e8dd5f28fe088 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Thu, 5 Oct 2023 11:54:37 -0400 Subject: [PATCH 07/11] luigi --- include/dpp/managed.h | 8 ++++---- include/dpp/snowflake.h | 31 +++++++++++++++++-------------- src/dpp/snowflake.cpp | 12 ++++++++++-- src/unittest/test.cpp | 5 ++++- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/include/dpp/managed.h b/include/dpp/managed.h index 191910b639..4d89a5d84b 100644 --- a/include/dpp/managed.h +++ b/include/dpp/managed.h @@ -66,19 +66,19 @@ namespace dpp { /** * @brief Destroy the managed object */ - virtual ~managed() = default; + virtual ~managed() noexcept = default; /** * @brief Copy assignment operator * @param rhs Object to copy */ - constexpr managed &operator=(const managed& rhs) = default; + constexpr managed &operator=(const managed& rhs) noexcept = default; /** * @brief Move assignment operator - * @param rhs Object to copy + * @param rhs Object to move from */ - constexpr managed &operator=(managed&& rhs) = default; + constexpr managed &operator=(managed&& rhs) noexcept = default; /** * @brief Get the creation time of this object according to Discord. diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index 226a8d88a9..1f947ed73d 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -24,7 +24,6 @@ #include #include #include -#include #include /** @@ -58,18 +57,18 @@ class DPP_EXPORT snowflake final { public: /** - * @brief Construct a snowflake object - */ + * @brief Construct a snowflake object + */ constexpr snowflake() noexcept = default; /** - * @brief Copy a snowflake object - */ + * @brief Copy a snowflake object + */ constexpr snowflake(const snowflake &rhs) noexcept = default; /** - * @brief Move a snowflake object - */ + * @brief Move a snowflake object + */ constexpr snowflake(snowflake &&rhs) noexcept = default; /** @@ -101,6 +100,16 @@ class DPP_EXPORT snowflake final { */ snowflake(std::string_view string_value) noexcept; + /** + * @brief Construct a snowflake object from an unsigned integer in a string + * + * On invalid string the value will be 0 + * @param string_value A snowflake value + */ + template >> + snowflake(const T &string_value) noexcept : snowflake(std::string_view{string_value}) {} + /* ^ this exists to preserve `message_cache.find(std::get(event.get_parameter("message_id")));`*/ + /** * @brief Copy value from another snowflake * @@ -166,13 +175,7 @@ class DPP_EXPORT snowflake final { * * @param snowflake_val snowflake value as a string */ - inline bool operator==(std::string_view snowflake_val) const noexcept { - uint64_t v; - auto [end, err] = std::from_chars(snowflake_val.data(), snowflake_val.data() + snowflake_val.size(), v); - if (end != snowflake_val.data() + snowflake_val.size()) // parse error - return false; - return *this == v; - } + bool operator==(std::string_view snowflake_val) const noexcept; /** * @brief Comparison operator with an integer diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 5f7ad6e844..4b2d8a3c46 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -32,12 +32,20 @@ snowflake::snowflake(std::string_view string_value) noexcept { } snowflake& snowflake::operator=(std::string_view string_value) noexcept { - auto [end, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); - if (end != string_value.data() + string_value.size()) + auto [_, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); + if (err != std::errc{}) value = 0; return *this; } +bool snowflake::operator==(std::string_view snowflake_val) const noexcept { + uint64_t v; + auto [end, err] = std::from_chars(snowflake_val.data(), snowflake_val.data() + snowflake_val.size(), v); + if (err != std::errc{}) + return false; + return *this == v; +} + snowflake::operator json() const { /* Discord transfers snowflakes as strings for compatibility with javascript */ return std::to_string(value); diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 2764dd54ff..6c73a38267 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -206,7 +206,10 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b success = success && (dpp::snowflake{69} < dpp::snowflake{420} && (dpp::snowflake{69} < 420)); s = "69420"; success = success && s == 69420; - s = dpp::snowflake{"1337"}; + auto conversion_test = [](dpp::snowflake sl) { + return sl; + }; + s = conversion_test(std::string{"1337"}); success = success && s == 1337; success = success && dpp::snowflake{0} == 0; set_test(SNOWFLAKE, success); From 3f09d1666223ad3683a132c4e431044cd0212411 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Thu, 5 Oct 2023 11:57:17 -0400 Subject: [PATCH 08/11] mamma mia --- src/dpp/snowflake.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 4b2d8a3c46..2606375da5 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -26,8 +26,8 @@ namespace dpp { snowflake::snowflake(std::string_view string_value) noexcept { - auto [end, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); - if (end != string_value.data() + string_value.size()) + auto [_, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); + if (err != std::errc{}) value = 0; } From 85a18174868e40202a0280bc26b64f3b39f84b19 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Thu, 5 Oct 2023 12:24:20 -0400 Subject: [PATCH 09/11] javascript wins this one --- include/dpp/snowflake.h | 21 ++++++++++++--------- src/dpp/snowflake.cpp | 7 ------- src/unittest/test.cpp | 4 ++-- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index 1f947ed73d..a68d4cc009 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -108,7 +108,7 @@ class DPP_EXPORT snowflake final { */ template >> snowflake(const T &string_value) noexcept : snowflake(std::string_view{string_value}) {} - /* ^ this exists to preserve `message_cache.find(std::get(event.get_parameter("message_id")));`*/ + /* ^ this exists to preserve `message_cache.find(std::get(event.get_parameter("message_id")));` */ /** * @brief Copy value from another snowflake @@ -124,14 +124,6 @@ class DPP_EXPORT snowflake final { */ constexpr dpp::snowflake &operator=(dpp::snowflake&& rhs) noexcept = default; - /** - * @brief Assign value converted from a string to the snowflake - * - * On invalid string the value will be 0 - * @param snowflake_val snowflake value as a string - */ - dpp::snowflake &operator=(std::string_view snowflake_val) noexcept; - /** * @brief Assign integer value to the snowflake * @@ -143,6 +135,17 @@ class DPP_EXPORT snowflake final { return *this = dpp::snowflake{snowflake_val}; } + /** + * @brief Assign value converted from a string to the snowflake + * + * On invalid string the value will be 0 + * @param snowflake_val snowflake value as a string + */ + template >> + constexpr dpp::snowflake &operator=(T&& snowflake_val) noexcept { + return *this = dpp::snowflake{std::forward(snowflake_val)}; + } + /** * @brief Returns true if the snowflake holds an empty value (is 0) * diff --git a/src/dpp/snowflake.cpp b/src/dpp/snowflake.cpp index 2606375da5..72d566756c 100644 --- a/src/dpp/snowflake.cpp +++ b/src/dpp/snowflake.cpp @@ -31,13 +31,6 @@ snowflake::snowflake(std::string_view string_value) noexcept { value = 0; } -snowflake& snowflake::operator=(std::string_view string_value) noexcept { - auto [_, err] = std::from_chars(string_value.data(), string_value.data() + string_value.size(), value); - if (err != std::errc{}) - value = 0; - return *this; -} - bool snowflake::operator==(std::string_view snowflake_val) const noexcept { uint64_t v; auto [end, err] = std::from_chars(snowflake_val.data(), snowflake_val.data() + snowflake_val.size(), v); diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index be46b6cb68..84442f5e77 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -300,10 +300,10 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b s = "69420"; success = success && s == 69420; auto conversion_test = [](dpp::snowflake sl) { - return sl; + return sl.str(); }; s = conversion_test(std::string{"1337"}); - success = success && s == 1337; + success = success && s == 1337; /* THIS BREAKS (and i do not care very much): && s == conversion_test(dpp::snowflake{"1337"}); */ success = success && dpp::snowflake{0} == 0; set_test(SNOWFLAKE, success); } From 6addfb8a8838e4fb283ebd3738925bb020e3951b Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Fri, 6 Oct 2023 12:26:37 -0400 Subject: [PATCH 10/11] apply requested changes --- include/dpp/json.h | 4 +++- include/dpp/json_fwd.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/dpp/json.h b/include/dpp/json.h index bfbf3bebf9..14f95ffd95 100644 --- a/include/dpp/json.h +++ b/include/dpp/json.h @@ -26,5 +26,7 @@ #endif namespace dpp { - using json = nlohmann::json; + +using json = nlohmann::json; + } diff --git a/include/dpp/json_fwd.h b/include/dpp/json_fwd.h index e5d8870ea8..6f4ecb3594 100644 --- a/include/dpp/json_fwd.h +++ b/include/dpp/json_fwd.h @@ -26,5 +26,7 @@ #endif namespace dpp { - using json = nlohmann::json; + +using json = nlohmann::json; + } From 1c2f625785d4377881b363faf8fd8a5a9c0f51cf Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Fri, 6 Oct 2023 12:30:18 -0400 Subject: [PATCH 11/11] ah yes i need to save the file --- include/dpp/snowflake.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dpp/snowflake.h b/include/dpp/snowflake.h index a68d4cc009..40cbe0e268 100644 --- a/include/dpp/snowflake.h +++ b/include/dpp/snowflake.h @@ -74,7 +74,7 @@ class DPP_EXPORT snowflake final { /** * @brief Construct a snowflake from an integer value * - * @throw dpp::logic_exception on assigning a negative value. the function is noexcept if the type given is unsigned + * @throw dpp::logic_exception on assigning a negative value. The function is noexcept if the type given is unsigned * @param snowflake_val snowflake value as an integer type */ template >> @@ -127,7 +127,7 @@ class DPP_EXPORT snowflake final { /** * @brief Assign integer value to the snowflake * - * @throw dpp::logic_exception on assigning a negative value. the function is noexcept if the type given is unsigned + * @throw dpp::logic_exception on assigning a negative value. The function is noexcept if the type given is unsigned * @param snowflake_val snowflake value as an integer type */ template >>