Skip to content

Commit

Permalink
more stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Mishura4 committed Oct 3, 2023
1 parent 734611a commit 8cd7aac
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 17 deletions.
9 changes: 7 additions & 2 deletions include/dpp/managed.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
103 changes: 90 additions & 13 deletions include/dpp/snowflake.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.h>
#include <stdint.h>
#include <functional>
#include <cstdint>
#include <charconv>

/**
* @brief The main namespace for D++ functions. classes and types
Expand Down Expand Up @@ -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 <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
constexpr snowflake(T snowflake_val) noexcept(std::is_unsigned_v<T>) : value(static_cast<std::make_unsigned_t<T>>(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<T>) {
/* 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 <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
constexpr dpp::snowflake &operator=(T snowflake_val) noexcept(std::is_unsigned_v<T>) {
return *this = dpp::snowflake{snowflake_val};
}

/**
Expand All @@ -99,21 +151,46 @@ 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
*
* @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 <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
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
Expand Down
3 changes: 2 additions & 1 deletion src/dpp/snowflake.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
************************************************************************************/
#include <dpp/snowflake.h>
#include <charconv>
#include <string>

namespace dpp {

Expand All @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/unittest/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down

0 comments on commit 8cd7aac

Please sign in to comment.