given this example
struct Outer<T>(*mut T);
impl<T> Outer<T> {
pub fn new(value: &mut T) -> Outer<T> {
Outer(value as *mut T)
}
}
struct Inner(pub i32);
impl Inner {
pub fn do_thing(&self) {
println!("did the thing {}", self.0);
}
}
fn main() {
let outer = Outer::new(Inner(2));
outer.do_thing() // error: do_thing doesnt exist
}
how would i expose the methods of Inner as methods of Outer
im trying to achieve what Box is doing
You have to reborrow the pointer in order to implement Deref (playground):
impl<T: ?Sized> Deref for Outer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.0 }
}
}
Answer from before the edit below:
The clean way is to have methods that return the inner type:
impl<T> Outer<T> {
pub fn get(&self) -> &T {
&self.0
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
pub fn into_inner(self) -> T {
self.0
}
}
This is more useful when the inner type isn't pub (you can just do self.0 for the same effect as all three methods), but is a common pattern that users of rust libraries expect.
The other way is to implement Deref and DerefMut. This is messier because it's a very strong API commitment: you now have all the methods of the inner type added to the outer type unconditionally, and gain any future methods. It also means that any namespace collisions between the wrapper and the target are hard to notice, which is why things like Arc::get_mut are associated functions instead of methods. If you use this, consider changing methods on the wrapper to associated functions (don't take a self parameter).
impl<T> Deref for Outer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
Let's say I have a mutable structure (i32 in the example code for simplicity) which should be shared between threads. I can use Mutex for it (and Arc for memory management). But I want to have RAII wrapper for data lock to make some specific interface of data modification, track unlocks etc.
Here the draft (I don't know which lifetime specify for MutexGuard):
use std::sync::{Arc, Mutex, MutexGuard};
pub struct SharedData {
data: Arc<Mutex<i32>>
}
impl SharedData {
pub fn new(value: i32) -> Self {
SharedData {
data: Arc::new(Mutex::new(value))
}
}
pub fn lock(&self) -> LockedSharedData<'_> {
LockedSharedData::new(self.data.clone())
}
}
pub struct LockedSharedData<'a> {
_data: Arc<Mutex<i32>>,
guard: MutexGuard<'a, i32>
}
impl<'a> LockedSharedData<'a> {
fn new(data: Arc<Mutex<i32>>) -> Self {
LockedSharedData {
guard: data.lock().unwrap(),
_data: data
}
}
pub fn get(&self) -> i32 {
*self.guard
}
pub fn inc(&mut self) {
*self.guard += 1;
}
}
It predictable doesn't compile - https://rust.godbolt.org/z/4rEe3fWxK.
How to fix this pattern implementation?
My problem is I want to have a transparent wrapper and implemented Into<underlying> for it. Unfortunately, rust's orphan rules forbid it. Here is a simple example:
#[repr(transparent)]
pub struct MyWrapper<T>(pub T);
impl<T> Into<T> for MyWrapper<T> {
fn into(self) -> T {
self.0
}
}
The question is is there any way I can implement it? I'm using macro to generate impl for all types I'm currently using but it looks very awkward and dirty.
You can implement the Deref trait instead. The Deref docs contain the following example which is almost identical to your code:
use std::ops::Deref;
struct DerefExample<T> {
value: T
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}
You can implement it in a regular impl block:
#[repr(transparent)]
pub struct MyWrapper<T>(pub T);
impl<T> MyWrapper<T> {
pub fn into(self) -> T {
self.0
}
}
fn main() {
let wrapped : MyWrapper<f32> = MyWrapper::<f32>(3.4f32);
let unwrapped : f32 = wrapped.into();
println!("{}", unwrapped);
}
Given a struct that wraps a pointer,
pub struct Ptr<T> {
ptr: T
}
Is it possible to declare that T must be a raw pointer type? eg *mut SomeStruct or *const SomeStruct.
Without this, I'm unable to perform operations like &*self.ptr within a method, since Rust doesn't know ptr can be treated like a pointer.
Note that this can be made to work:
pub struct Ptr<T> {
ptr: *mut T
}
But in that case, it hard-codes *mut, where we might want *const in other cases.
See: this answer to give some context.
I'm not convinced this is worth doing, but if you're sure then you can just write a trait:
pub trait RawPtr: Sized {
type Value;
fn as_const(self) -> *const Self::Value {
self.as_mut() as *const _
}
fn as_mut(self) -> *mut Self::Value {
self.as_const() as *mut _
}
}
impl<T> RawPtr for *const T {
type Value = T;
fn as_const(self) -> Self { self }
}
impl<T> RawPtr for *mut T {
type Value = T;
fn as_mut(self) -> Self { self }
}
Your can then require P: RawPtr when implementing functions:
pub struct Ptr<P> {
ptr: P
}
impl<P: RawPtr> Ptr<P> {
unsafe fn get(self) -> P::Value
where P::Value: Copy
{
*self.ptr.as_const()
}
}
Additionally, it's possible to define methods that are only available when P is a mutable pointer:
impl<T> Ptr<*mut T> {
unsafe fn get_mut(&mut self) -> *mut T {
self.ptr
}
}
I am trying to make some kind of ffi to a library written in C, but got stuck. Here is a test case:
extern crate libc;
use libc::{c_void, size_t};
// this is C library api call
unsafe fn some_external_proc(_handler: *mut c_void, value: *const c_void,
value_len: size_t) {
println!("received: {:?}" , std::slice::from_raw_buf(
&(value as *const u8), value_len as usize));
}
// this is Rust wrapper for C library api
pub trait MemoryArea {
fn get_memory_area(&self) -> (*const u8, usize);
}
impl MemoryArea for u64 {
fn get_memory_area(&self) -> (*const u8, usize) {
(unsafe { std::mem::transmute(self) }, std::mem::size_of_val(self))
}
}
impl <'a> MemoryArea for &'a str {
fn get_memory_area(&self) -> (*const u8, usize) {
let bytes = self.as_bytes();
(bytes.as_ptr(), bytes.len())
}
}
#[allow(missing_copy_implementations)]
pub struct Handler<T> {
obj: *mut c_void,
}
impl <T> Handler<T> {
pub fn new() -> Handler<T> { Handler{obj: std::ptr::null_mut(),} }
pub fn invoke_external_proc(&mut self, value: T) where T: MemoryArea {
let (area, area_len) = value.get_memory_area();
unsafe {
some_external_proc(self.obj, area as *const c_void,
area_len as size_t)
};
}
}
// this is Rust wrapper user code
fn main() {
let mut handler_u64 = Handler::new();
let mut handler_str = Handler::new();
handler_u64.invoke_external_proc(1u64); // OK
handler_str.invoke_external_proc("Hello"); // also OK
loop {
match std::io::stdin().read_line() {
Ok(line) => {
let key =
line.trim_right_matches(|&: c: char| c.is_whitespace());
//// error: `line` does not live long enough
// handler_str.invoke_external_proc(key)
}
Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break ,
Err(error) => panic!("io error: {}" , error),
}
}
}
Rust playpen
I get "line does not live long enough" error if I uncomment line inside the loop. In fact, I realize that Rust is afraid that I could store short-living reference to a slice somewhere inside Handler object, but I quite sure that I wouldn't, and I also know, that it is safe to pass pointers to the external proc (actually, memory is immidiately copied at the C library side).
Is there any way for me to bypass this check?
The problem is that you are incorrectly parameterizing your struct, when you really want to do it for the function. When you create your current Handler, the struct will be specialized with a type that includes a lifetime. However, the lifetime of line is only for the block, so there can be no lifetime for Handler that lasts multiple loop iterations.
What you want is for the lifetime to be tied to the function call, not the life of the struct. As you noted, if you put the lifetime on the struct, then the struct is able to store references of that length. You don't need that, so put the generic type on the function instead:
impl Handler {
pub fn new() -> Handler { Handler{obj: std::ptr::null_mut(),} }
pub fn invoke_external_proc<T>(&mut self, value: T) where T: MemoryArea {
let (area, area_len) = value.get_memory_area();
unsafe {
some_external_proc(self.obj, area as *const c_void,
area_len as size_t)
};
}
}
Amended answer
Since you want to specialize the struct on a type, but don't care too much about the lifetime of the type, let's try this:
#[allow(missing_copy_implementations)]
pub struct Handler<T: ?Sized> {
obj: *mut c_void,
}
impl<T: ?Sized> Handler<T> {
pub fn new() -> Handler<T> { Handler{ obj: std::ptr::null_mut() } }
pub fn invoke_external_proc(&mut self, value: &T) where T: MemoryArea {
let (area, area_len) = value.get_memory_area();
unsafe {
some_external_proc(self.obj, area as *const c_void,
area_len as size_t)
};
}
}
Here, we allow the type to be unsized. Since you can't pass an unsized value as a parameter, we now have to take a reference instead. We also have to change the impl:
impl MemoryArea for str {
fn get_memory_area(&self) -> (*const u8, usize) {
let bytes = self.as_bytes();
(bytes.as_ptr(), bytes.len())
}
}