Some updates
This commit is contained in:
parent
56e4ca45a9
commit
ee4c7540f0
@ -196,12 +196,4 @@ ErrorType ts::findError(std::string key){
|
|||||||
for(auto elm : avariableErrors)
|
for(auto elm : avariableErrors)
|
||||||
if(elm.name == key) return elm;
|
if(elm.name == key) return elm;
|
||||||
return ErrorType{1, key, "undefined"};
|
return ErrorType{1, key, "undefined"};
|
||||||
}
|
|
||||||
|
|
||||||
CommandResult CommandResult::Success = {avariableErrors[0], ""};
|
|
||||||
CommandResult CommandResult::NotImplemented = {avariableErrors[2], ""};
|
|
||||||
|
|
||||||
CommandResultPermissionError::CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg) : CommandResult(findError(0x0A08), "") {
|
|
||||||
this->extraProperties["failed_permid"] = std::to_string((int16_t) error);
|
|
||||||
this->_type = PERM_ERROR;
|
|
||||||
}
|
}
|
211
src/Error.h
211
src/Error.h
@ -184,15 +184,22 @@ namespace ts {
|
|||||||
std::map<std::string, std::string> extra_properties;
|
std::map<std::string, std::string> extra_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum struct command_result_type {
|
||||||
|
detailed = 0b00,
|
||||||
|
error = 0b10,
|
||||||
|
bulked = 0b11
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
|
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
|
||||||
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
|
* return command_result{permission::b_virtualserver_select_godmode}; => movabs rax,0xa08001700000001; ret; (Only if there is no destructor!)
|
||||||
* return command_result{error::vs_critical, "unknown error"}; => To a lot of code
|
* return command_result{error::vs_critical, "unknown error"}; => To a lot of code
|
||||||
*/
|
*/
|
||||||
|
struct command_result_bulk;
|
||||||
struct command_result { /* fixed size of 8 (64 bits) */
|
struct command_result { /* fixed size of 8 (64 bits) */
|
||||||
static constexpr uint64_t MASK_ERROR = ~((uint64_t) 1 << (sizeof(error::type) * 8));
|
static constexpr uint64_t MASK_ERROR = ~((uint64_t) 1 << (sizeof(error::type) * 8));
|
||||||
static constexpr uint64_t MASK_PERMISSION = ~((uint64_t) 1 << (sizeof(permission::PermissionType) * 8));
|
static constexpr uint64_t MASK_PERMISSION = ~((uint64_t) 1 << (sizeof(permission::PermissionType) * 8));
|
||||||
|
static constexpr uint64_t MASK_PTR = ~((uint64_t) 0b111U);
|
||||||
|
|
||||||
static constexpr uint8_t OFFSET_ERROR = (8 - sizeof(error::type)) * 8;
|
static constexpr uint8_t OFFSET_ERROR = (8 - sizeof(error::type)) * 8;
|
||||||
static constexpr uint8_t OFFSET_PERMISSION = (8 - sizeof(permission::PermissionType) - sizeof(error::type)) * 8;
|
static constexpr uint8_t OFFSET_PERMISSION = (8 - sizeof(permission::PermissionType) - sizeof(error::type)) * 8;
|
||||||
@ -205,44 +212,108 @@ namespace ts {
|
|||||||
* bits [64 - sizeof(error::type);64] => error type | Usually evaluates to [48;64]
|
* bits [64 - sizeof(error::type);64] => error type | Usually evaluates to [48;64]
|
||||||
* bits [64 - sizeof(error::type) - sizeof(permission::PermissionType);64 - sizeof(error::type)] => permission id | Usually evaluates to [32;48]
|
* bits [64 - sizeof(error::type) - sizeof(permission::PermissionType);64 - sizeof(error::type)] => permission id | Usually evaluates to [32;48]
|
||||||
*/
|
*/
|
||||||
uint64_t data = 0;
|
uint64_t data{0};
|
||||||
|
|
||||||
/* Test for mode 1 as described before */
|
/* Test for mode 1 as described before */
|
||||||
static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 62);
|
static_assert(sizeof(permission::PermissionType) * 8 + sizeof(error::type) * 8 <= 60);
|
||||||
|
|
||||||
|
[[nodiscard]] inline command_result_type type() const {
|
||||||
|
return (command_result_type) (this->data & 0b11U);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool has_error() const {
|
||||||
|
switch (this->type()) {
|
||||||
|
case command_result_type::bulked:
|
||||||
|
return false;
|
||||||
|
case command_result_type::error:
|
||||||
|
return this->error_code() != error::ok;
|
||||||
|
case command_result_type::detailed:
|
||||||
|
return this->details()->error_id != error::ok;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only valid for command_result_type::error */
|
||||||
[[nodiscard]] inline error::type error_code() const {
|
[[nodiscard]] inline error::type error_code() const {
|
||||||
if(this->is_detailed()) return this->details()->error_id;
|
assert(this->type() == command_result_type::error);
|
||||||
|
|
||||||
return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR);
|
return (error::type) ((this->data >> OFFSET_ERROR) & MASK_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only valid for command_result_type::error */
|
||||||
[[nodiscard]] inline bool is_permission_error() const {
|
[[nodiscard]] inline bool is_permission_error() const {
|
||||||
|
assert(this->type() == command_result_type::error);
|
||||||
return this->error_code() == error::server_insufficeient_permissions;
|
return this->error_code() == error::server_insufficeient_permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only valid for command_result_type::error */
|
||||||
[[nodiscard]] inline permission::PermissionType permission_id() const {
|
[[nodiscard]] inline permission::PermissionType permission_id() const {
|
||||||
if(this->is_detailed()) return (permission::PermissionType) -1; /* not supported */
|
assert(this->type() == command_result_type::error);
|
||||||
|
|
||||||
return (permission::PermissionType) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION);
|
return (permission::PermissionType) ((this->data >> OFFSET_PERMISSION) & MASK_PERMISSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline const detailed_command_result* details() const { return (detailed_command_result*) this->data; }
|
/* only valid for command_result_type::detailed */
|
||||||
[[nodiscard]] inline detailed_command_result* details() { return (detailed_command_result*) this->data; }
|
[[nodiscard]] inline const detailed_command_result* details() const {
|
||||||
|
assert(this->type() == command_result_type::detailed);
|
||||||
[[nodiscard]] inline bool is_detailed() const {
|
return (detailed_command_result*) (this->data & MASK_PTR);
|
||||||
return (this->data & 0x1UL) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::unique_ptr<detailed_command_result> release_details() {
|
/* only valid for command_result_type::detailed */
|
||||||
if(!this->is_detailed()) return nullptr;
|
[[nodiscard]] inline detailed_command_result* details() {
|
||||||
|
assert(this->type() == command_result_type::detailed);
|
||||||
|
return (detailed_command_result*) (this->data & MASK_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // Dont use release_details. Use release_data instead
|
||||||
|
[[nodiscard]] inline std::unique_ptr<detailed_command_result> release_details() {
|
||||||
|
auto type = this->type();
|
||||||
|
if(type != command_result_type::detailed) return nullptr;
|
||||||
|
|
||||||
auto result = this->details();
|
auto result = this->details();
|
||||||
this->data = 0;
|
this->data = 0;
|
||||||
return std::unique_ptr<detailed_command_result>{result};
|
return std::unique_ptr<detailed_command_result>{result};
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Attention: Releases the internal detailed pointer! */
|
/* only valid for command_result_type::bulked */
|
||||||
inline CommandResult as_command_result();
|
[[nodiscard]] inline const std::vector<command_result>* bulks() const {
|
||||||
|
assert(this->type() == command_result_type::bulked);
|
||||||
|
return (std::vector<command_result>*) (this->data & MASK_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only valid for command_result_type::bulked */
|
||||||
|
[[nodiscard]] inline std::vector<command_result>* bulks() {
|
||||||
|
assert(this->type() == command_result_type::bulked);
|
||||||
|
return (std::vector<command_result>*) (this->data & MASK_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // Dont use release_bulks. Use release_data instead
|
||||||
|
[[nodiscard]] inline std::vector<command_result> release_bulks() {
|
||||||
|
auto type = this->type();
|
||||||
|
if(type != command_result_type::bulked) return {};
|
||||||
|
|
||||||
|
std::vector<command_result> result{};
|
||||||
|
auto bulks = reinterpret_cast<std::vector<command_result>*>(this->data);
|
||||||
|
result.swap(*bulks);
|
||||||
|
delete bulks;
|
||||||
|
this->data = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void release_data() {
|
||||||
|
auto type = this->type();
|
||||||
|
if(type == command_result_type::bulked) {
|
||||||
|
auto bulks = this->bulks();
|
||||||
|
delete bulks;
|
||||||
|
} else if(type == command_result_type::detailed) {
|
||||||
|
auto details = this->details();
|
||||||
|
delete details;
|
||||||
|
}
|
||||||
|
this->data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _NDEBUG /* We dont need to secure that because gcc deduct us to an uint64_t and the only advantage is the mem leak test which is deactivated anyways */
|
#ifndef _NDEBUG /* We dont need to secure that because gcc deduct us to an uint64_t and the only advantage is the mem leak test which is deactivated anyways */
|
||||||
command_result(command_result&) = delete;
|
command_result(command_result&) = delete;
|
||||||
@ -255,7 +326,7 @@ namespace ts {
|
|||||||
command_result() = default;
|
command_result() = default;
|
||||||
|
|
||||||
explicit command_result(permission::PermissionType permission) {
|
explicit command_result(permission::PermissionType permission) {
|
||||||
this->data = 0x01; /* the the type to 1 */
|
this->data = (uint64_t) command_result_type::error;
|
||||||
|
|
||||||
this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR;
|
this->data |= (uint64_t) error::server_insufficeient_permissions << OFFSET_ERROR;
|
||||||
this->data |= (uint64_t) permission << OFFSET_PERMISSION;
|
this->data |= (uint64_t) permission << OFFSET_PERMISSION;
|
||||||
@ -263,7 +334,7 @@ namespace ts {
|
|||||||
|
|
||||||
|
|
||||||
explicit command_result(error::type error) {
|
explicit command_result(error::type error) {
|
||||||
this->data = 0x01; /* the the type to 1 */
|
this->data = (uint64_t) command_result_type::error;
|
||||||
|
|
||||||
this->data |= (uint64_t) error << (8 - sizeof(error::type)) * 8;
|
this->data |= (uint64_t) error << (8 - sizeof(error::type)) * 8;
|
||||||
}
|
}
|
||||||
@ -273,16 +344,19 @@ namespace ts {
|
|||||||
assert(((uintptr_t) details_ptr & 0x03U) == 0); // must be aligned!
|
assert(((uintptr_t) details_ptr & 0x03U) == 0); // must be aligned!
|
||||||
|
|
||||||
this->data = (uintptr_t) details_ptr;
|
this->data = (uintptr_t) details_ptr;
|
||||||
|
this->data |= (uint64_t) command_result_type::detailed;
|
||||||
|
|
||||||
details_ptr->error_id = error;
|
details_ptr->error_id = error;
|
||||||
details_ptr->extra_properties["extra_msg"] = message;
|
details_ptr->extra_properties["extra_msg"] = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
command_result(error::type error, const std::map<std::string, std::string>& properties) : command_result{error, std::string{""}} {
|
command_result(error::type error, const std::map<std::string, std::string>& properties) : command_result{error, std::string{""}} {
|
||||||
assert(this->is_detailed());
|
assert(this->type() == command_result_type::detailed);
|
||||||
this->details()->extra_properties = properties;
|
this->details()->extra_properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit command_result(command_result_bulk&&);
|
||||||
|
|
||||||
#ifndef _NDEBUG
|
#ifndef _NDEBUG
|
||||||
/* if we're not using any debug we dont have to use a deconstructor. A deconstructor prevent a direct uint64_t return as described above */
|
/* if we're not using any debug we dont have to use a deconstructor. A deconstructor prevent a direct uint64_t return as described above */
|
||||||
~command_result() {
|
~command_result() {
|
||||||
@ -295,6 +369,50 @@ namespace ts {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(command_result) == 8);
|
static_assert(sizeof(command_result) == 8);
|
||||||
|
|
||||||
|
struct command_result_bulk {
|
||||||
|
friend struct command_result;
|
||||||
|
public:
|
||||||
|
command_result_bulk() = default;
|
||||||
|
command_result_bulk(command_result&& result) { this->results.push_back(std::forward<command_result>(result)); }
|
||||||
|
~command_result_bulk() {
|
||||||
|
for(auto& result : this->results)
|
||||||
|
result.release_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reserve(size_t length) {
|
||||||
|
this->results.reserve(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void emplace_result(permission::PermissionType permission) {
|
||||||
|
this->results.emplace_back(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void emplace_result(error::type error) {
|
||||||
|
this->results.emplace_back(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void emplace_result(error::type error, const std::string& message) {
|
||||||
|
this->results.emplace_back(error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline auto begin() { return this->results.begin(); }
|
||||||
|
[[nodiscard]] inline auto end() { return this->results.end(); }
|
||||||
|
[[nodiscard]] inline auto cbegin() const { return this->results.cbegin(); }
|
||||||
|
[[nodiscard]] inline auto cend() const { return this->results.cend(); }
|
||||||
|
private:
|
||||||
|
std::vector<command_result> results{};
|
||||||
|
};
|
||||||
|
|
||||||
|
inline command_result::command_result(ts::command_result_bulk &&bulk) {
|
||||||
|
auto bulks = new std::vector<command_result>{};
|
||||||
|
assert(((uintptr_t) bulks & 0x03U) == 0); // must be aligned!
|
||||||
|
|
||||||
|
this->data = (uintptr_t) bulks;
|
||||||
|
this->data |= (uint64_t) command_result_type::bulked;
|
||||||
|
|
||||||
|
bulks->swap(bulk.results);
|
||||||
|
}
|
||||||
|
|
||||||
struct ErrorType {
|
struct ErrorType {
|
||||||
public:
|
public:
|
||||||
static ErrorType Success;
|
static ErrorType Success;
|
||||||
@ -334,63 +452,6 @@ namespace ts {
|
|||||||
extern const std::vector<ErrorType> avariableErrors;
|
extern const std::vector<ErrorType> avariableErrors;
|
||||||
extern ErrorType findError(uint16_t errorId);
|
extern ErrorType findError(uint16_t errorId);
|
||||||
extern ErrorType findError(std::string key);
|
extern ErrorType findError(std::string key);
|
||||||
|
|
||||||
enum CommandResultType {
|
|
||||||
GENERAL,
|
|
||||||
PERM_ERROR
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommandResult {
|
|
||||||
public:
|
|
||||||
static CommandResult Success;
|
|
||||||
static CommandResult NotImplemented;
|
|
||||||
|
|
||||||
CommandResult(const CommandResult& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {}
|
|
||||||
CommandResult(CommandResult&& ref) : _type(ref._type), error(ref.error), extraProperties(ref.extraProperties) {}
|
|
||||||
CommandResult(ErrorType error, const std::string &extraMsg = "") : error(std::move(error)) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; }
|
|
||||||
CommandResult(std::string error, const std::string &extraMsg = "") : error(findError(std::move(error))) { if(extraMsg.empty()) return; /*extraProperties["extramsg"] = extraMsg; */extraProperties["extra_msg"] = extraMsg; }
|
|
||||||
CommandResult() : CommandResult(ErrorType::Success, ""){}
|
|
||||||
CommandResult(ErrorType error, std::map<std::string, std::string> details) : error(error), extraProperties(std::move(details)) {}
|
|
||||||
|
|
||||||
bool operator==(const CommandResult& ref){
|
|
||||||
return this->error == ref.error && ref.extraProperties == this->extraProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandResult& operator=(const CommandResult& ref)= default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if fail
|
|
||||||
*/
|
|
||||||
bool operator!() const {
|
|
||||||
return this->error != ErrorType::Success;
|
|
||||||
}
|
|
||||||
virtual CommandResultType type(){ return _type; }
|
|
||||||
|
|
||||||
ErrorType error;
|
|
||||||
std::map<std::string, std::string> extraProperties;
|
|
||||||
CommandResultType _type = CommandResultType::GENERAL;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommandResultPermissionError : public CommandResult {
|
|
||||||
public:
|
|
||||||
CommandResultPermissionError(permission::PermissionType error, const std::string &extraMsg = "");
|
|
||||||
};
|
|
||||||
|
|
||||||
CommandResult command_result::as_command_result() {
|
|
||||||
if(this->is_detailed()) {
|
|
||||||
const auto details = this->details();
|
|
||||||
auto result = CommandResult{findError(details->error_id), details->extra_properties};
|
|
||||||
this->release_details();
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
const auto code = this->error_code();
|
|
||||||
auto error = findError(this->error_code());
|
|
||||||
if(code == error::server_insufficeient_permissions)
|
|
||||||
return CommandResultPermissionError{(permission::PermissionType) this->permission_id()};
|
|
||||||
else
|
|
||||||
return CommandResult{error};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _NDEBUG
|
#undef _NDEBUG
|
@ -61,7 +61,7 @@ command_result test3() {
|
|||||||
void eval_test(command_result x) {
|
void eval_test(command_result x) {
|
||||||
if(x.is_detailed()) {
|
if(x.is_detailed()) {
|
||||||
cout << "Detailed!" << endl;
|
cout << "Detailed!" << endl;
|
||||||
x.release_details();
|
x.release_data();
|
||||||
} else {
|
} else {
|
||||||
auto a = x.permission_id();
|
auto a = x.permission_id();
|
||||||
auto b = x.error_code();
|
auto b = x.error_code();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user