diff --git a/include/mg_exceptions.hpp b/include/mg_exceptions.hpp index be7421836..53a338b86 100644 --- a/include/mg_exceptions.hpp +++ b/include/mg_exceptions.hpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -13,45 +13,96 @@ #include #include +#include +#include namespace mg_exception { -struct NotEnoughMemoryException : public std::exception { - const char *what() const throw() { return "Not enough memory!"; } -}; + +// Instead of writing this utility function, we could have used `fmt::format`, but that's not an ideal option here +// because that would introduce dependency that would be propagated to the client code (if exceptions here would be +// used). Since the functionality here is not complex + the code is not on a critical path, we opted for a pure C++ +// solution. +template +std::string StringSerialize(FirstArg &&firstArg, Args &&...args) { + std::stringstream stream; + stream << firstArg; + ((stream << " " << args), ...); + return stream.str(); +} + struct UnknownException : public std::exception { - const char *what() const throw() { return "Unknown exception!"; } + const char *what() const noexcept override { return "Unknown exception!"; } }; + +struct NotEnoughMemoryException : public std::exception { + NotEnoughMemoryException() + : message_{ + StringSerialize("Not enough memory! For more details please visit", "https://memgr.ph/memory-control")} {} + const char *what() const noexcept override { return message_.c_str(); } + + private: + std::string message_; +}; + struct AllocationException : public std::exception { - const char *what() const throw() { return "Could not allocate memory!"; } + AllocationException() + : message_{StringSerialize("Could not allocate memory. For more details please visit", + "https://memgr.ph/memory-control")} {} + const char *what() const noexcept override { return message_.c_str(); } + + private: + std::string message_; }; + struct InsufficientBufferException : public std::exception { - const char *what() const throw() { return "Buffer is not sufficient to process procedure!"; } + const char *what() const noexcept override { return "Buffer is not sufficient to process procedure!"; } }; + struct OutOfRangeException : public std::exception { - const char *what() const throw() { return "Index out of range!"; } + const char *what() const noexcept override { return "Index out of range!"; } }; + struct LogicException : public std::exception { - const char *what() const throw() { return "Logic exception, check the procedure signature!"; } + const char *what() const noexcept override { return "Logic exception, check the procedure signature!"; } }; + struct DeletedObjectException : public std::exception { - const char *what() const throw() { return "Object is deleted!"; } + const char *what() const noexcept override { return "Object is deleted!"; } }; + struct InvalidArgumentException : public std::exception { - const char *what() const throw() { return "Invalid argument!"; } + const char *what() const noexcept override { return "Invalid argument!"; } }; + struct InvalidIDException : public std::exception { - const char *what() const throw() { return "Invalid ID!"; } + InvalidIDException() : message_{"Invalid ID!"} {} + explicit InvalidIDException(std::uint64_t identifier) : message_{StringSerialize("Invalid ID =", identifier)} {} + const char *what() const noexcept override { return message_.c_str(); } + + private: + std::string message_; }; + struct KeyAlreadyExistsException : public std::exception { - const char *what() const throw() { return "Key you are trying to set already exists!"; } + KeyAlreadyExistsException() : message_{"Key you are trying to set already exists!"} {} + explicit KeyAlreadyExistsException(const std::string &key) + : message_{StringSerialize("Key you are trying to set already exists! KEY = ", key)} {} + const char *what() const noexcept override { return message_.c_str(); } + + private: + std::string message_; }; + struct ImmutableObjectException : public std::exception { - const char *what() const throw() { return "Object you are trying to change is immutable!"; } + const char *what() const noexcept override { return "Object you are trying to change is immutable!"; } }; + struct ValueConversionException : public std::exception { - const char *what() const throw() { return "Error in value conversion!"; } + const char *what() const noexcept override { return "Error in value conversion!"; } }; + struct SerializationException : public std::exception { - const char *what() const throw() { return "Error in serialization!"; } + const char *what() const noexcept override { return "Error in serialization!"; } }; + } // namespace mg_exception diff --git a/include/mgp.hpp b/include/mgp.hpp index 28fe7d152..bbf6883c1 100644 --- a/include/mgp.hpp +++ b/include/mgp.hpp @@ -53,11 +53,6 @@ class NotFoundException : public std::exception { std::string message_; }; -class NotEnoughMemoryException : public std::exception { - public: - const char *what() const throw() { return "Not enough memory!"; } -}; - class MustAbortException : public std::exception { public: explicit MustAbortException(const std::string &message) : message_(message) {} @@ -2534,7 +2529,7 @@ inline bool Node::HasLabel(std::string_view label) const { inline Relationships Node::InRelationships() const { auto relationship_iterator = mgp::vertex_iter_in_edges(ptr_, memory); if (relationship_iterator == nullptr) { - throw NotEnoughMemoryException(); + throw mg_exception::NotEnoughMemoryException(); } return Relationships(relationship_iterator); } @@ -2542,7 +2537,7 @@ inline Relationships Node::InRelationships() const { inline Relationships Node::OutRelationships() const { auto relationship_iterator = mgp::vertex_iter_out_edges(ptr_, memory); if (relationship_iterator == nullptr) { - throw NotEnoughMemoryException(); + throw mg_exception::NotEnoughMemoryException(); } return Relationships(relationship_iterator); } @@ -3652,7 +3647,7 @@ inline RecordFactory::RecordFactory(mgp_result *result) : result_(result) {} inline const Record RecordFactory::NewRecord() const { auto record = mgp::result_new_record(result_); if (record == nullptr) { - throw NotEnoughMemoryException(); + throw mg_exception::NotEnoughMemoryException(); } return Record(record); }