I have a wrapper around a C-API:
#[repr(transparent)]
pub struct Request(http_request_t);
This wrapper provides several methods for interacting with the request:
impl Request {
pub fn bytes_received(&self) -> usize {
unsafe {
http_request_bytes_received(&self.0 as *const http_request_t)
}
}
}
Unfortunately the C-API is not so strict about const
-correctness and thus has a type signature of usize http_request_bytes_received(*http_request_t)
which is dutifully converted by bindgen
to http_request_bytes_received(*mut http_request_t) -> usize
.
Now I could just cast my way out of this, but casting from &T
to *mut T
can easily lead to undefined behaviour (and it's a nasty cast). But it might be OK as http_request_bytes_received
doesn't mutate http_request_t
.
A possible alternative would be to use UnsafeCell
so http_request_t
is interior mutable:
#[repr(transparent)]
pub struct Request(UnsafeCell<http_request_t>);
impl Request {
pub fn bytes_received(&self) -> usize {
unsafe {
http_request_bytes_received(self.0.get())
}
}
}
Is this approach sound and would there any serious downsides?
(I imagine it might limit some Rust optimizations and will make Request
!Sync
)