Compare commits
2 Commits
540b8dc103
...
834d5d5964
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
834d5d5964 | ||
|
|
0f41240eeb |
@@ -1,16 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(redis_playground LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
|
||||
project(redis_playground LANGUAGES CXX)
|
||||
|
||||
find_package(hiredis CONFIG REQUIRED)
|
||||
|
||||
add_library(proj_warnings INTERFACE)
|
||||
target_compile_options(proj_warnings INTERFACE -Wall -Werror -Wextra -Wpedantic)
|
||||
|
||||
add_library(expected INTERFACE src/expected.h)
|
||||
target_link_libraries(expected INTERFACE proj_warnings)
|
||||
|
||||
add_executable(main ./src/main.cc)
|
||||
target_link_libraries(main PRIVATE proj_warnings hiredis::hiredis)
|
||||
target_link_libraries(main PRIVATE proj_warnings expected hiredis::hiredis)
|
||||
|
||||
98
src/expected.h
Normal file
98
src/expected.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef EXPECTED_H
|
||||
#define EXPECTED_H
|
||||
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
struct BadExpectedAccess : std::exception {
|
||||
const char* what() const noexcept override {
|
||||
return "bad access to `Expected` without expected value";
|
||||
}
|
||||
};
|
||||
|
||||
class Unexpected {
|
||||
public:
|
||||
explicit Unexpected(std::string_view err_msg) : err_msg_(err_msg) {}
|
||||
|
||||
std::string_view error() const noexcept { return err_msg_; }
|
||||
|
||||
private:
|
||||
std::string err_msg_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Expected {
|
||||
static_assert(!std::is_reference_v<T>,
|
||||
"Expected<T> does not support reference types");
|
||||
|
||||
public:
|
||||
Expected()
|
||||
requires(std::is_default_constructible_v<T>)
|
||||
: val_(std::in_place_index<0>) {}
|
||||
|
||||
Expected(const T& val) : val_(val) {}
|
||||
Expected(T&& val) : val_(std::move(val)) {}
|
||||
|
||||
Expected(const Unexpected& err) : val_(err) {}
|
||||
Expected(Unexpected&& err) : val_(std::move(err)) {}
|
||||
|
||||
bool has_value() const noexcept { return val_.index() == 0; }
|
||||
|
||||
explicit operator bool() const noexcept { return has_value(); }
|
||||
|
||||
T& value() & {
|
||||
if (!has_value()) throw BadExpectedAccess();
|
||||
return std::get<0>(val_);
|
||||
}
|
||||
|
||||
const T& value() const& {
|
||||
if (!has_value()) throw BadExpectedAccess();
|
||||
return std::get<0>(val_);
|
||||
}
|
||||
|
||||
T&& value() && {
|
||||
if (!has_value()) throw BadExpectedAccess();
|
||||
return std::move(std::get<0>(val_));
|
||||
}
|
||||
|
||||
const T&& value() const&& {
|
||||
if (!has_value()) throw BadExpectedAccess();
|
||||
return std::move(std::get<0>(val_));
|
||||
}
|
||||
|
||||
std::string_view error() const noexcept {
|
||||
return has_value() ? "" : std::get<1>(val_).error();
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<T, Unexpected> val_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class Expected<void> {
|
||||
public:
|
||||
Expected() {}
|
||||
|
||||
Expected(const Unexpected& err) : err_(err) {}
|
||||
Expected(Unexpected&& err) : err_(std::move(err)) {}
|
||||
|
||||
bool has_value() const noexcept { return !err_.has_value(); }
|
||||
explicit operator bool() const noexcept { return has_value(); }
|
||||
|
||||
void value() const {
|
||||
if (!has_value()) throw BadExpectedAccess();
|
||||
}
|
||||
|
||||
std::string_view error() const noexcept {
|
||||
return err_.has_value() ? err_.value().error() : "";
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<Unexpected> err_;
|
||||
};
|
||||
|
||||
#endif // EXPECTED_H
|
||||
18
src/main.cc
18
src/main.cc
@@ -1,6 +1,5 @@
|
||||
#include <hiredis/hiredis.h>
|
||||
|
||||
#include <expected>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -12,6 +11,8 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "expected.h"
|
||||
|
||||
struct FieldVal {
|
||||
std::string field, val;
|
||||
};
|
||||
@@ -73,7 +74,7 @@ class RedisClient {
|
||||
if (ctx_) redisFree(ctx_);
|
||||
}
|
||||
|
||||
std::expected<void, std::string> xadd(const XaddReq& req) noexcept {
|
||||
Expected<void> xadd(const XaddReq& req) noexcept {
|
||||
// todo: safe guard against invalid requests
|
||||
|
||||
std::stringstream ss;
|
||||
@@ -84,15 +85,15 @@ class RedisClient {
|
||||
auto reply = submit_cmd(ss.str());
|
||||
|
||||
if (!reply) {
|
||||
return std::unexpected(ctx_->errstr);
|
||||
return Unexpected(ctx_->errstr);
|
||||
} else if (reply->type == REDIS_REPLY_ERROR) {
|
||||
return std::unexpected(reply->str ? reply->str : "unknown error");
|
||||
return Unexpected(reply->str ? reply->str : "unknown error");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::expected<XreadRes, std::string> xread(const XreadReq& req) noexcept {
|
||||
Expected<XreadRes> xread(const XreadReq& req) noexcept {
|
||||
// todo: safe guard against invalid requests
|
||||
|
||||
std::stringstream ss;
|
||||
@@ -105,14 +106,13 @@ class RedisClient {
|
||||
auto reply = submit_cmd(ss.str());
|
||||
|
||||
if (!reply) {
|
||||
return std::unexpected(ctx_->errstr);
|
||||
return Unexpected(ctx_->errstr);
|
||||
} else if (reply->type == REDIS_REPLY_ERROR) {
|
||||
return std::unexpected(reply->str ? reply->str : "unknown reply error");
|
||||
return Unexpected(reply->str ? reply->str : "unknown reply error");
|
||||
} else if (reply->type == REDIS_REPLY_NIL) {
|
||||
return {};
|
||||
} else if (reply->type != REDIS_REPLY_ARRAY) {
|
||||
return std::unexpected(
|
||||
std::format("unexpected reply type {}", reply->type));
|
||||
return Unexpected(std::format("unexpected reply type {}", reply->type));
|
||||
}
|
||||
|
||||
XreadRes res;
|
||||
|
||||
Reference in New Issue
Block a user