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
Serialize & Deserialize #88
Comments
Here is what a remote derive implementation looks like, a lot of hassle and hackery: [derive(Serialize, Deserialize)]
#[serde(remote = "clap_verbosity_flag::Verbosity")]
struct VerbosityDef {
#[serde(getter = "clap_verbosity_flag::Verbosity::verbose")]
pub verbose: u8,
#[serde(getter = "clap_verbosity_flag::Verbosity::quiet")]
pub quiet: u8,
}
pub trait VerbosityRemoteGetters {
fn verbose(&self) -> u8;
fn quiet(&self) -> u8;
}
impl VerbosityRemoteGetters for clap_verbosity_flag::Verbosity {
fn verbose(&self) -> u8 {
let debug_string = format!("{:#?}", self);
let re = Regex::new(r"verbose: (?<verbose>[\d]+)").unwrap();
let output = re.captures(&debug_string).unwrap();
let string_value = output.name("verbose").unwrap().as_str();
let calc = string_value.parse::<u8>().unwrap();
calc
}
fn quiet(&self) -> u8 {
let debug_string = format!("{:#?}", self);
let re = Regex::new(r"quiet: (?<quiet>[\d]+)").unwrap();
let output = re.captures(&debug_string).unwrap();
let string_value = output.name("quiet").unwrap().as_str();
let calc = string_value.parse::<u8>().unwrap();
calc
}
}
impl From<VerbosityDef> for clap_verbosity_flag::Verbosity {
fn from(def: VerbosityDef) -> clap_verbosity_flag::Verbosity {
clap_verbosity_flag::Verbosity::new(def.verbose, def.quiet)
}
}
#[derive(Serialize, Deserialize, Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[serde(with = "VerbosityDef")]
#[command(flatten)]
verbose: clap_verbosity_flag::Verbosity,
} Or, I could just copy/paste out the core of the implementation in fewer lines: clap-verbosity-flag/src/lib.rs Lines 64 to 90 in f44eadc
|
To be clear, are those your use cases or theoretical use cases? As for the serialization format, I consider any non-textual serialization format to be a non-starter. As a user, entering random numbers in two fields and dealing with how those fields interact makes no sense and I would expect to just say |
I have both of those use cases in the project I'm working on. You're looking at a trimmed down Designing a query for particular nodes in a huge DAG is hard; it's way easier to present them to the user for clicking/visual feedback of what is selected. They can run multiple times from the GUI context until it is right, and then serialize out the command string for later use. Sample output for each option in the GUI makes it easy to figure out which options are in use, and applies to both |
I don't have super-strong opinions here (I've since dropped this as a dep), but I feel like there is a lot of value in standardizing the underlying tooling layer for the CLI hello world because it creates consistent UX outcomes for users. The lack of Not exposing the numerics means that displaying the outcome as a range slider in the HTML GUI still requires mapping it myself from string, making the |
There was a straightforward PR thrown up for discussion over at #65, effectively looking for a
Serialize
andDeserialize
implementation for this library. The requests from @epage:Use Cases
Instrumentation
If an entire
args
object is being passed intotracing
it is quite nice to have aSerialize
so thatderive
works. I don't want to have toimpl Serialize for Args
for this reason. If I don't do some serialization then I end up withDebug
and that is super-verbose.Args From
<Elsewhere>
This
some-cli gui
command spins up a server and opens a browser to an HTML page. Eventually that HTML page makes a network request back to the server, which contains a serialized form of the arguments that would have been passed in. That's going to be JSON (cause it's coming from the web), deserializing intoArgs
(from the above example).Starts the server:
(Complicated configuration happens in a browser.)
Data from a "configuration finished!" network request passed back in to the CLI entry point:
Design Space
There are basically only two reasonable options here to represent configuration since it is a
count
.As Separate
u8
sGiven that we have
-q
and-v[vvv]
exposed as separate args this separation doesn't seem particularly egregious. Further, since the struct can be constructed withclap_verbosity_flag::Verbosity::new(2, 4)
, any serialization that doesn't give you both of those values is lossy.Being able to represent the error conditions (
error: the argument '--quiet...' cannot be used with '--verbose...'
) that can be triggered by command line usage is reasonable—even though typically it would never get through::parse()
.As A Single
i16
Since we have the
conflicts_with
lockout from the primaryclap
use case, we could choose to serialize them into a single value, in spite of it being lossy. Take a page from thelog
mapping, and doquiet
as-(count)
.An
i16
gives us way more bits than we need, but there isn't ani9
.This approach can't support
{ quiet: 4, verbosity: 4 }
like a manually constructed struct can.I'm in favor of the separate
u8
s for representation fidelity reasons and nominate reopening and accepting #65.The text was updated successfully, but these errors were encountered: