Finally the package built properly , so there is documentation on my project on docs.rs available .
Consider the method mmtkvdb::Env::open_dbs
(source code available behind the link) which opens several databases:
unsafe fn open_dbs<'a, K, V, C>(
&self,
metas: impl IntoIterator<
IntoIter = impl Iterator<Item = &'a DbOptions<K, V, C, Option<CString>>> + ExactSizeIterator
>
) -> Result<Vec<Db<K, V, C>>, Error> where
K: ?Sized + Storable,
V: ?Sized + Storable,
C: Constraint;
Each database may use different types for their keys and values. Thus, the DbOptions
builder uses the typestate pattern and has type arguments K
and V
for the key and value type.
The open_dbs
method opens several databases at once (it will have to acquire a mutex for it and do a few other things, so when multiple databases are opened, it may make sense to only do that once, which is why I allow passing multiple DbOptions
through an iterator). However, while the signature of open_dbs
is generic over different K
and V
types, it does not support opening databases with different keys (or values) in one call, because K
and V
are particular types for each invocation of open_dbs
.
To overcome the limitation of only being able to open multiple databases with the same key (and value) types, I wanted to use dyn
objects. The caller of open_dbs
could then downcast each element in the result according to the (known) types K
and V
.
In practice, the code quickly gets very complex though. I might just leave the interface as is and accept the overhead of opening differently-typed databases in multiple calls.
I wonder, however, if similar problems occurred in other contexts where there are lists of structs with type arguments passed to a function that returns a list of different structs with the same type arguments (in my example above: K, V, C
appear both in the arguments as well as in the result of the function).