-
Notifications
You must be signed in to change notification settings - Fork 999
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat (facade): simple argument parser #1747
Conversation
With the search work I'm doing I need to parse a lot of parameters and the parsing code for it would grow over multiple hundreds of lines (given that I already have a few). Most of it is annoying boilerplate so I want to finally simplify it a little. I want to add a proper argument parser instead of always looping manually, converting values, checking errors, etc. I want to use it for search and replace current mapping code in some command families. Given that you'll be working on new commands as well with ACL, what do you think of it? What should be included? I placed it in the redis_parser_test just because I was to lazy to add a separate target to compile some code, its just a playground for now. My thoughts. Check this function out for example https://github.com/dranikpg/dragonfly/blob/search-named-return/src/server/search/search_family.cc#L97 What is an issue?
UPD: See the example in search family |
33fdeaa
to
099969e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is still WIP, but still had a few comments to add :)
c432b1b
to
4e52094
Compare
I like the approach and it does simplify a lot of the bounds checking etc.
The ACL commands are very easy to parse, only P.s. I will take more detailed look later today. |
src/facade/cmd_arg_parser.h
Outdated
|
||
// Get optional error if occured | ||
std::optional<ErrorInfo> Error() { | ||
return std::move(error_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
safety suggestion:
return std::move(error_); | |
auto rv = std::move(error_); | |
error_.reset(); | |
return rv; |
then put CHECK(!error_.has_value());
in CmdArgParser
's destructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today I learned that moving from an optional still keeps the value 😳
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you made me double check 😆
a moved-from std::optional still contains a value, but the value itself is moved from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually double checked as well 🤣
Today I learned that moving from an optional still keeps the value
It's up to the value_type of what the state of that value will be.
For the optional, has_value
will return true. This is on par with the std::move
semantics:
Unless otherwise specified, all standard library objects that have been moved from are placed in a "valid but unspecified state", meaning the object's class invariants hold (so functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from):
@dranikpg
try return std::exchange(error_, {})
for a slick one liner 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's up to the value_type of what the state of that value will be.
I meant the state of the optional won't be nullopt
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
src/server/search/search_family.cc
Outdated
// RETURN {num} [{ident} AS {name}...] | ||
if (ArgS(args, i) == "RETURN") { | ||
if (i + 1 >= args.size()) { | ||
(*cntx)->SendError(kSyntaxErr); | ||
return nullopt; | ||
} | ||
|
||
uint64_t num_fields = args.size(); | ||
if (!absl::SimpleAtoi(ArgS(args, i + 1), &num_fields)) { | ||
(*cntx)->SendError(kSyntaxErr); | ||
return nullopt; | ||
} | ||
|
||
i += 1; | ||
|
||
if (parser.Check("RETURN").ExpectTail(1)) { | ||
size_t num_fields = parser.Next().Int<size_t>(); | ||
alias_list = SearchParams::FieldAliasList{}; | ||
while (alias_list->size() < num_fields) { | ||
if (++i >= args.size()) { | ||
(*cntx)->SendError(kSyntaxErr); | ||
return nullopt; | ||
} | ||
|
||
string_view ident = ArgS(args, i); | ||
string_view alias = ident; | ||
|
||
if (i + 2 < args.size() && absl::EqualsIgnoreCase(ArgS(args, i + 1), "AS")) { | ||
alias = ArgS(args, i + 2); | ||
i += 2; | ||
} | ||
|
||
string_view ident = parser.Next(); | ||
string_view alias = parser.Check("AS").ExpectTail(1) ? parser.Next() : string_view{ident}; | ||
alias_list->emplace_back(ident, alias); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
namespace facade { | ||
|
||
// Utility class for easily parsing command options from argument lists. | ||
struct CmdArgParser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it actually ok to keep this header only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, probably not (noticing 2s after giving the approval)
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just for moving things into a .cc file
Signed-off-by: Vladislav Oleshko <[email protected]>
|
||
#include <absl/strings/ascii.h> | ||
#include <absl/strings/match.h> | ||
#include <absl/strings/numbers.h> | ||
|
||
#include "base/logging.h" | ||
#include "facade/error.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved all function longer than 3 lines and all functions that have some sependencies (absl and our stuff)
sorry for my late input 👨🍳 Great work, I left some comments 🚀 |
Signed-off-by: Vladislav Oleshko <[email protected]>
Adds a simple parser for handling command arguments
See comments below