user1685095
user1685095

Reputation: 6121

Can I use types to express that at least one argument should be Some for a constructor?

With some help, I've been able to create this code which tries to describe a range of numbers:

#[derive(Debug, Default)]
struct Inclusive;
#[derive(Debug, Default)]
struct Exclusive;

#[derive(Deserialize)]
struct Range<S, E, V: Ord>(
    Option<V>,
    Option<V>,
    #[serde(skip)] S,
    #[serde(skip)] E,
);


fn main () {
    let data = "[[1, null]]";
    let rs: Vec<Range<Inclusive, Exclusive, i32>> = serde_json::from_str(data)
         .expect("Error");
    println!("Range from {:?} to {:?}", rs[0].0, rs[0].1);
}

Is it possible to describe via types that Range should have at least one bound so that [null, null] would throw a deserialization error at runtime?

Upvotes: 1

Views: 74

Answers (1)

Peter Hall
Peter Hall

Reputation: 58735

It's better to model the problem to capture the invariants statically, rather than relying on runtime checks. Matthieu's suggestion of using an enum might look like this:

enum RangeBound<V> {
    Between(V, V),
    LowerBounded(V),
    UpperBounded(V),
}

struct Range<S, E, V: Ord>(
    RangeBound<V>,
    #[serde(skip)] S,
    #[serde(skip)] E,
);

It is not possible to create a RangeBound without at least one value.

This approach will probably require a custom Deserialize implementation though.

Upvotes: 2

Related Questions