Wrapping zero-copy struct using an owned type struct

Working with external crates I've noticed that it isn't uncommon for a struct to be "zero-copy", i.e. only take references. For example (not including lifetimes):

struct MyZeroCopy {
   data1: &str,
   data2: &str,
   ...
}

impl MyZeroCopy {
    pub fn new(data: &str) -> Self {
        // process/parse data and populate data1, data2, ... from data
       ...
    }
}

What is the best strategy for wrapping MyZeroCopy using an owned type (in this case e.g. String)? Something that would have a signature like:

struct OwnedWrapper {
    my_zero_copy: MyZeroCopy,
    ...
}

impl OwnedWrapper {
    pub fn new(data: String) -> Self {
        // pass data to MyZeroCopy
        ...
    }
}

The naive implementation would require a self-referential struct. What other options are available? Can MyZeroCopy be made friendlier to allow such wrappers?

1 Like

Ultimately the type would need to take ownership instead of using &str references. You could e.g. use Cow<'a, str> to support either in the same struct, or use two versions of the struct.

Not sure I fully understand. Let's say OwnedWrapper is an external crate which I don't want to expose directly (and I can't change) but I want to make it accessible via my own OwnedWrapper that only takes a String.

In that case I'd need to take ownership of both the String as well as an instance of MyZeroCopy which would create a self-referential struct.

Then create your own owned version of that other crate's struct.

In other words, short of changing the external crate's public interface, there are no other options.

I was hoping there would some workarounds which are not very nasty. I've looked at some self-referential solutions/crates but I wasn't sure I understood impacts/side-effects well. I've also seen cases when a ref is declared as 'static and then use transmute to change from non-static to static lifetime which might work in my case but again, not sure I fully understand all consequences.

If anyone knows of blog posts (or wants to write one) about explaining and solving some self-referential problems, I'd be definitely interested.

I've struggled with this recently as well. In my case creating an owned version would mean almost forking the entire crate, which is an option but not ideal. I opted to not make the struct owned after all, though that would've made more sense for my use case, so I'm interested in the topic as well.

There are some crates which can help with it, but my personal opinion is that they are sketchy unsafe-wise.