Skip to content

Commit

Permalink
feat(json_family): Add support of the JSON legacy mode (#3284)
Browse files Browse the repository at this point in the history
  • Loading branch information
BagritsevichStepan authored Aug 6, 2024
1 parent 7df72fd commit 75452a7
Show file tree
Hide file tree
Showing 9 changed files with 1,768 additions and 1,047 deletions.
5 changes: 5 additions & 0 deletions src/facade/cmd_arg_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ struct CmdArgParser {
}
}

// returns next value if exists or default value
template <class T = std::string_view> auto NextOrDefault(T default_value = {}) {
return HasNext() ? Next<T>() : default_value;
}

// check next value ignoring case and consume it
void ExpectTag(std::string_view tag);

Expand Down
1 change: 1 addition & 0 deletions src/facade/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ std::string UnknownSubCmd(std::string_view subcmd, std::string_view cmd);

extern const char kSyntaxErr[];
extern const char kWrongTypeErr[];
extern const char kWrongJsonTypeErr[];
extern const char kKeyNotFoundErr[];
extern const char kInvalidIntErr[];
extern const char kInvalidFloatErr[];
Expand Down
1 change: 1 addition & 0 deletions src/facade/facade.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ string ConfigSetFailed(string_view config_name) {

const char kSyntaxErr[] = "syntax error";
const char kWrongTypeErr[] = "-WRONGTYPE Operation against a key holding the wrong kind of value";
const char kWrongJsonTypeErr[] = "-WRONGTYPE wrong JSON type of path value";
const char kKeyNotFoundErr[] = "no such key";
const char kInvalidIntErr[] = "value is not an integer or out of range";
const char kInvalidFloatErr[] = "value is not a valid float";
Expand Down
2 changes: 2 additions & 0 deletions src/facade/op_status.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ std::string_view StatusToMsg(OpStatus status) {
return kKeyNotFoundErr;
case OpStatus::WRONG_TYPE:
return kWrongTypeErr;
case OpStatus::WRONG_JSON_TYPE:
return kWrongJsonTypeErr;
case OpStatus::OUT_OF_RANGE:
return kIndexOutOfRange;
case OpStatus::INVALID_FLOAT:
Expand Down
1 change: 1 addition & 0 deletions src/facade/op_status.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum class OpStatus : uint16_t {
INVALID_VALUE,
OUT_OF_RANGE,
WRONG_TYPE,
WRONG_JSON_TYPE,
TIMED_OUT,
OUT_OF_MEMORY,
INVALID_FLOAT,
Expand Down
61 changes: 29 additions & 32 deletions src/server/detail/wrapped_json_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,15 @@ using JsonExpression = jsoncons::jsonpath::jsonpath_expression<JsonType>;
template <typename T>
using JsonPathEvaluateCallback = absl::FunctionRef<T(std::string_view, const JsonType&)>;

template <typename T = Nothing> class MutateCallbackResult {
public:
template <typename T = Nothing> struct MutateCallbackResult {
MutateCallbackResult() = default;

explicit MutateCallbackResult(bool should_be_deleted) : should_be_deleted_(should_be_deleted_) {
}

MutateCallbackResult(bool should_be_deleted, T&& value)
: should_be_deleted_(should_be_deleted), value_(std::forward<T>(value)) {
}

bool HasValue() const {
return value_.has_value();
}

T&& GetValue() && {
return std::move(value_).value();
MutateCallbackResult(bool should_be_deleted_, T value_)
: should_be_deleted(should_be_deleted_), value(std::move(value_)) {
}

bool ShouldBeDeleted() const {
return should_be_deleted_;
}

private:
bool should_be_deleted_;
std::optional<T> value_;
bool should_be_deleted = false;
std::optional<T> value;
};

template <typename T>
Expand Down Expand Up @@ -81,15 +64,23 @@ template <typename T> class JsonCallbackResult {

JsonCallbackResult() = default;

explicit JsonCallbackResult(bool legacy_mode_is_enabled) {
explicit JsonCallbackResult(bool legacy_mode_is_enabled, bool save_first_result = false)
: save_first_result_(save_first_result) {
if (!legacy_mode_is_enabled) {
result_ = JsonV2Result{};
}
}

void AddValue(T value) {
if (IsV1()) {
details::OptionalEmplace(std::move(value), &AsV1());
if (!save_first_result_) {
details::OptionalEmplace(std::move(value), &AsV1());
} else {
auto& as_v1 = AsV1();
if (!as_v1.has_value()) {
details::OptionalEmplace(std::move(value), &as_v1);
}
}
} else {
AsV2().emplace_back(std::move(value));
}
Expand Down Expand Up @@ -117,6 +108,7 @@ template <typename T> class JsonCallbackResult {

private:
std::variant<JsonV1Result, JsonV2Result> result_;
bool save_first_result_ = false;
};

class WrappedJsonPath {
Expand All @@ -137,14 +129,15 @@ class WrappedJsonPath {
}

template <typename T>
JsonCallbackResult<T> Evaluate(const JsonType* json_entry, JsonPathEvaluateCallback<T> cb) const {
return Evaluate(json_entry, cb, IsLegacyModePath());
JsonCallbackResult<T> Evaluate(const JsonType* json_entry, JsonPathEvaluateCallback<T> cb,
bool save_first_result) const {
return Evaluate(json_entry, cb, save_first_result, IsLegacyModePath());
}

template <typename T>
JsonCallbackResult<T> Evaluate(const JsonType* json_entry, JsonPathEvaluateCallback<T> cb,
bool legacy_mode_is_enabled) const {
JsonCallbackResult<T> eval_result{legacy_mode_is_enabled};
bool save_first_result, bool legacy_mode_is_enabled) const {
JsonCallbackResult<T> eval_result{legacy_mode_is_enabled, save_first_result};

auto eval_callback = [&cb, &eval_result](std::string_view path, const JsonType& val) {
eval_result.AddValue(cb(path, val));
Expand Down Expand Up @@ -172,10 +165,10 @@ class WrappedJsonPath {
auto mutate_callback = [&cb, &mutate_result](std::optional<std::string_view> path,
JsonType* val) -> bool {
auto res = cb(path, val);
if (res.HasValue()) {
mutate_result.AddValue(std::move(res).GetValue());
if (res.value.has_value()) {
mutate_result.AddValue(std::move(res.value).value());
}
return res.ShouldBeDeleted();
return res.should_be_deleted;
};

if (HoldsJsonPath()) {
Expand Down Expand Up @@ -217,7 +210,11 @@ class WrappedJsonPath {
return is_legacy_mode_path_;
}

private:
bool RefersToRootElement() const {
auto path = path_.view();
return path.empty() || path == kV1PathRootElement || path == kV2PathRootElement;
}

bool HoldsJsonPath() const {
return std::holds_alternative<json::Path>(parsed_path_);
}
Expand Down
11 changes: 0 additions & 11 deletions src/server/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,6 @@ using facade::kWrongTypeErr;

#endif // RETURN_ON_BAD_STATUS

#ifndef RETURN_UNEXPECTED

#define RETURN_UNEXPECTED(x) \
do { \
if (!(x)) { \
return (x).get_unexpected(); \
} \
} while (0)

#endif // RETURN_UNEXPECTED

#ifndef GET_OR_SEND_UNEXPECTED

#define GET_OR_SEND_UNEXPECTED(expr) \
Expand Down
Loading

0 comments on commit 75452a7

Please sign in to comment.