2

I want to implement a module that encapsulates different types of messages with different types and quantity of fields that enables to send and receive them using the same send and receive functions, and then determine what variant of the message is, with what fields; using match.

I have the following enum and functions (simplified) :

pub enum Message { Start { field1 : type1 }, End { field2 : type2 }, } impl Message { pub fn send( &self ) { send(self); } pub fn receive( &mut self ) { *self = receive(); } } 

I want to use them as follows:

Send:

let message = Message::Start; message.send(); 

Receive

let message = Message; message.receive(); match message { Start{field1} => { ... } End{field2} => { ... } }; 

When calling the receive function, I get a compiler error that says "use of possibly-uninitialized message". It makes sense because this variable has not been initialized. How can I achieve this behavior with no errors?

5
  • 5
    Are you sure you need self for receive? Can't it be an associated function fn receive() -> Self? Commented Sep 6, 2022 at 14:55
  • 2
    This is a strange pattern, in the sense that it doesn't make sense for an uninitialized instance of Message to exist. What is a default message supposed to be? Why should a message send and receive itself? Shouldn't it be the job of another component? Commented Sep 6, 2022 at 15:25
  • 1
    I agree with the other commenters. Your struct layout makes it really hard for the compiler to understand what's going on. It will never be able to figure out that receive is supposed to get an uninitialized message and initialize it. That's just not a feature of Rust. Commented Sep 6, 2022 at 16:26
  • For the sake of completeness, you can technically do "out" parameters with MaybeUninit<Message> but that's fraught with perils and requires unsafe. Commented Sep 6, 2022 at 16:49
  • Thank you for the clarification. Your approach makes more sense to me and seems correct instead of my initial thought Commented Sep 6, 2022 at 19:14

1 Answer 1

5

It sounds like you're looking for an associated function which returns a Message.

impl Message { pub fn receive() -> Message { // Do whatever and return a Message::Start or Message::End as needed. } } // To call... let my_message = Message::receive(); 

Associated functions are sort of like static functions in C++, and they use :: on the type name itself as the call syntax. At runtime, it's just another ordinary function, but it's in the Message namespace so it's easier to find for programmers at write time.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.