DPD-
DPD-

Reputation: 490

Rust disable struct construction

How can I disable struct construction but maintaining pattern matching in Rust?

Let's see an example:

struct OrderedPair(pub u32, pub u32);

impl OrderedPair {
    fn new(a: u32, b: u32) -> Self {
        if a < b {
            Self(a, b)
        } else {
            Self(b, a)
        }
    }
}

It's obvious that I want to inhibit the construction of such struct (e.g. OrderedPair(2, 1)) and to use only the new method, in order to preserve the invariant. I know of 3 ways to do this:

  1. Make private the fields
struct OrderedPair(u32, u32);
  1. Add a private dummy field
struct OrderedPair(pub u32, pub u32, ());
  1. Make the struct non-exhaustive
#[non_exhaustive]
struct OrderedPair(pub u32, pub u32);

The issues are that with 1 I cannot access the members at all and with all three I cannot use pattern matching

let OrderedPair(min, max) = my_ordered_pair;

So is there a way to block struct construction but allow pattern matching?

I know that if we declare a mutable variable of that type with public access to members then the invariant can be broken by manually changing the members, but for now avoiding the struct constructor is enough.

Upvotes: 3

Views: 839

Answers (1)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382112

Instead of doing pattern matching directly on the fields, you can do it on a returned tupple:

#[derive(Clone, Copy)]
pub struct OrderedPair {
    a: u32,
    b: u32,
}
impl OrderedPair {
    pub fn new(a: u32, b: u32) -> Self {
        let (a, b) = if a < b { (a, b) } else { (b, a) };
        Self { a, b }
    }
    pub fn content(self) -> (u32, u32) {
        (self.a, self.b)
    }
}

Upvotes: 4

Related Questions