We run into this same issue with gimli where we want to do zero-copy parsing of many DWARF things, but then run into self-referential issues when we want to bundle the raw mmap of the debug info with its parsed form (say to stick them in a filename -> debug-info hashmap together).
We ended up creating a Reader trait that is similar to byte's Buf and BufMut traits. One can implement Reader with reference counting behind the scenes, but we just provide an implementation for slices0. It works OK, but now the whole code base is generic over a Reader and it feels a lot more complicated than it did with raw references.
cc @philipc
With cpp_demangle, I saw this issue coming before I started writing any code and there is a single nice place to encapsulate all generic ownership (where as with gimli there is no clear single place that would be the thing that owns the data or not, it would need to be ref-counted).
I ended up making demangled symbols generic over some T: AsRef<[u8]> and then the internal parsed AST items store indices into the input rather than slices or anything like that:
/// A mangled symbol that has been parsed into an AST.
///
/// This is generic over some storage type `T` which can be either owned or
/// borrowed.
pub struct Symbol<T: AsRef<[u8]> {
raw: T,
// These structures store indices pointing into `raw.as_ref()` rather than
// slices or reference-counted views..
substitutions: subs::SubstitutionTable,
parsed: ast::MangledName,
}
/// A `Symbol` which owns the underlying storage for the mangled name.
pub type OwnedSymbol = Symbol<Vec<u8>>;
/// A `Symbol` which borrows the underlying storage for the mangled name.
pub type BorrowedSymbol<'a> = Symbol<&'a [u8]>;
So, I’d like to conclude that:
-
Yes, this is totally a real problem, and not just in generators and async IO domains.
-
There are ways to work around this issue. Nevertheless, they are relatively painful for library authors, and require more effort than otherwise.
-
If a library’s author doesn’t go through that effort, then library consumers are hosed if they need owned versions.
0 Well slice and endianity.