#Rust Equivalent of Typescript's `type myString = 'Option1' | 'Option2' | 'Option3'` (union types)

16 messages · Page 1 of 1 (latest)

tribal geyser
#

Hey everyone! I'm looking for the rust idiomatic way to force a string variable to be included in a list of strings. I can't seem to make it work with enums, and I haven't found a rusty elegant way to do it:)
I come from a TS background, I'm a bit lost:

Do you know how to write this in Rust ?

`type myString = 'Option1' | 'Option2' | 'Option3'`

Thanks a lots

kindred fractal
#

There isn't a way to make a string whose value is exactly one of a few possibilities.

Enums are the way to do this. Since you said you're having trouble, can you elaborate? What kind of trouble is it?

tribal geyser
#

My usecase:
I'm using clap crate to get an input through CLI passed args,
And I'll match that input to call different APIs depending on the input
So I wanted a cool way to pre-type the input to make sure it's one of a few possibilities, and error out of it isn't

#

But I guess I can type it as a string, and error out in the _ => ...
part of the match function

kindred fractal
#

Usually you'd do this by converting from string to enum:

enum Opt {
  Option1,
  Option2,
  Option3,
}

match string {
  "Option1" => Ok(Opt::Option1),
  "Option2" => Ok(Opt::Option2),
  "Option3" => Ok(Opt::Option3),
  _ => Err(SomeError);
}
```Depending on what exactly you need to do, there's several small improvements you could make here, but this is the basic idea
tribal geyser
#

Okay:), works for me
thanks a lot for your time

#

'There isn't a way to make a string whose value is exactly one of a few possibilities.'

Do you know why though?

kindred fractal
#

Primarily because that's just an enum, but represented far less efficiently

#

Opts here is a single byte (actually less: there's some optimizations we do in some cases that can bitpack other things into that byte).

Option1, as a String, is 24 bytes (a pointer and two usizes), plus 7 bytes for the actual text, plus whatever extra bytes of spare capacity exist (if any), plus any allocator metadata (if any)

tribal geyser
#

Thanks a lot for your time:)

boreal arrow
#

@tribal geyser perhaps you have just not found the right clap api for it 😛

#

e.g. perhaps rust #[derive(clap::ArgEnum, Clone, Debug)] #[clap(rename_all = "snake_case")] pub enum Render { All, Map, }

sick monolith
#

?eval

use clap::Parser;

#[derive(Debug, clap::Parser)]
struct Args {
    #[clap(value_enum)]
    option: Opt,
}

#[derive(Debug, clap::ValueEnum, Clone)]
#[clap(rename_all = "PascalCase")]
enum Opt {
    Option1,
    Option2,
    Option3,
}

(
    Args::try_parse_from(["--option", "Option1"]),
    Args::try_parse_from(["--option", "Option2"]),
    Args::try_parse_from(["--option", "Option3"]),
    Args::try_parse_from(["--option", "other"]),
)
robust fernBOT
#
     Running `target/debug/playground`

(Ok(Args { option: Option1 }), Ok(Args { option: Option2 }), Ok(Args { option: Option3 }), Err(Error { inner: ErrorInner { kind: InvalidValue, context: [(InvalidArg, String("<OPTION>")), (InvalidValue, String("other")), (ValidValue, Strings(["Option1", "Option2", "Option3"]))], message: None, source: None, help_flag: Some("--help"), color_when: Auto, wait_on_exit: false, backtrace: None }, kind: InvalidValue, info: ["<OPTION>", "other", "Option1", "Option2", "Option3"] }))
tribal geyser
#

ohh that's awesome