Allowing multiple choices in a library API

Hello all

I'm struggling a bit with the best way to represent this in Rust. Let's say I'm the library writer. I'd like to give the library user the ability to instantiate an object with an variety of options. The library user may use all or none of these options, and, each option represents some distinct choice so shouldn't be provided twice.

If the object in question is called ForTheLibraryUser, I could write something like this:

impl ForTheLibraryUser {
    pub fn new(
        opt_1: Option<LibraryUserOpt1>,
        opt_2: Option<LibraryUserOpt2>,
    ) -> Self { ... }
}

But, this list of options is likely to grow over time, and, default function arguments not being allowed, I'd like not to have to make breaking changes to the API. So I was leaning towards something like:

impl ForTheLibraryUser {
    pub fn new(options: HashSet<LibraryUserOpt>) -> Self { ... }
}

pub enum LibraryUserOpt {
    Opt1(Opt1Details),
    Opt2(Opt2Details),
}

The trouble with this is:

  • There's nothing to stop the library user from passing in two LibraryUserOpt::Opt1 variants, each with a different value, and
  • The syntax within std::collections::HashSet for extracting potential options from a hashset is not well suited to this; because the enum variants hold values, I'd need to extract the objects in the HashSet using a predicate closure rather than an equality comparison (something like std::vec::Vec::pop_if), and there aren't any methods well-suited to that in HashSet.

Are there any better idioms for dealing with this?

Thanks in advance, and also after the event.

Can it be done with the Builder idiom? - Builder - Rust Design Patterns

I think builders are the right way to go here. Jiff makes heavy use of them. Example: Zoned in jiff - Rust

Thanks, yes, it mostly can. I think this is the lessest evil here.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.