rotty
rotty

Reputation: 33

When should I use `&mut self` vs. `&self` in Rust bindings for a C library?

I'm unsure when to use &mut self vs. just &self in the Rust bindings for the libzmq C API.

A bit of background: libzmq provides socket "objects", which have an API similar to the BSD socket API, and are represented by an opaque pointer in C. This pointer is really just a handle, similar to POSIX file descriptors, and the C API is designed so that it is not possible to obtain any references to memory behind that pointer.

Under these circumstances, is it safe and good API design to expose socket methods with an immutable self? As a concrete example, consider zmq_send():

int zmq_send (void *socket, void *buf, size_t len, int flags);

I think it can (and should) be exposed using immutable self, i.e.:

pub fn send(&self, data: &[u8], flags: i32) -> Result<()> { ... }

However, comparable Rust standard library methods use &mut self, e.g. std::io::Write::write(), as implemented by std::net::TcpStream. On the other hand, std::net::UdpStream::write() takes just &self. My guess is that &mut self is used just because it is an implementation of the Write trait, which in turn (I guess) uses &mut self to not constrain implementations of the trait.

I hope someone can back up or refute my speculations here -- I could not find anything specific about that topic in the Book or the Nomicon.

Upvotes: 3

Views: 596

Answers (1)

Chris Emerson
Chris Emerson

Reputation: 14041

In this case whether the object is mutated is secondary; the main question is "is it safe for two references to be used at the same time?". Would it be ok for two threads to call zmq_send (or other methods) on the same object at the same time, or (if the API allows that) via nested callbacks, etc?

If not, use &mut self and let Rust enforce the safety guarantees you need.

If it is safe, then maybe &self is appropriate, if zmq guarantees it's ok; this would be like Mutex::lock taking &self.

Upvotes: 5

Related Questions