0

I have a struct that is used by different functions. Instead of passing the struct as input to the different functions, I think I can implement the struct with all the functions that need to access it. However, there are certain fixed basic functions that I want to provide so that whenever the struct is created, I don't have to implement the same set of functions over and over again.

Put in another way, what I really want is the struct inheritance: I have certain set of methods associated with struct and user can add their custom functions to struct and allow them to access the data contained in data. Is there anyway able to do so?

Concretely, suppose I have a struct called AppContext and the fixed set of functions are new and bdev_name:

pub struct AppContext {
    bdev: *mut raw::spdk_bdev,
    bdev_desc: *mut raw::spdk_bdev_desc,
    bdev_io_channel: *mut raw::spdk_io_channel,
    buff: *mut c_char,
    bdev_name: *const c_char,
}

impl AppContext {
    pub fn new() -> Self {
        let context: AppContext;
        unsafe {
            context = mem::uninitialized();
        }
        context
    }

    pub fn bdev_name(&mut self, name: &str) {
        self.bdev_name = CString::new(name)
            .expect("Couldn't create a string")
            .into_raw()
    }
}

Now, when I use this struct, I do:

let mut context = AppContext::new();
context.bdev_name("Nvme0n1");

I want to add one extra function (say end()) that can work on the data within the context struct. However, end() is very domain specific function and needed in a specific module, and thus it's not a good idea to implement as part of the context struct.

Is there any way I can workaround the issue (i.e. add custom function to predefined struct)?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
xxks-kkk
  • 2,336
  • 3
  • 28
  • 48
  • Your usage of `mem::uninitialized` is completely inappropriate and dangerous. – Shepmaster Oct 04 '18 at 19:03
  • Your implementation of `bdev_name` easily creates memory leaks once it's called twice. – Shepmaster Oct 04 '18 at 19:04
  • I'm new to Rust and I'm working on the FFI with some C library. For C, I can do `struct AppContext hello_context = {}`. I'm not sure what's the best way in Rust. – xxks-kkk Oct 04 '18 at 19:06
  • Can you elaborate more on what memory leaks I can create and what's the approate way to implement it. I simply want to set some `char*` for the undelying C struct. – xxks-kkk Oct 04 '18 at 19:07
  • 1
    Presumably you should be setting those pointers to NULL so you know if they have been initialized or not. Uninitialized values can be *literally* any value that just happens to be in that chunk of memory at that point in time. Uninitialized memory is a classic door to allowing security vulnerabilities. – Shepmaster Oct 04 '18 at 19:12
  • @Shepmaster I take a look at links that you listed. If I use extension trait, I think I still need to reimplement the `new` and `bdev_name` methods in the extension trait implementation? Is there any way to simply inherit not reimplement? Thanks! – xxks-kkk Oct 04 '18 at 19:21
  • 1
    Rust has no inheritance ([What is the best way to inherit a struct in Rust 1.3?](https://stackoverflow.com/q/32736170/155423) / [Is it possible for one struct to extend an existing struct, keeping all the fields?](https://stackoverflow.com/q/32552593/155423) / [How to avoid code duplication of different structs with semantically equal fields/properties?](https://stackoverflow.com/q/39429218/155423)). I don't know why you think you need to reimplement the methods. – Shepmaster Oct 04 '18 at 19:25

0 Answers0