You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The drawback of this is that when implementing the PrimaryKey trait, we can't use any custom serialization method of which the output is of variable length.
Example
Here is an actual use case I've worked on. Consider the following type:
enumAssetInfo{// bank module native coinNative{denom:String},// cw20 tokenCw20{contract_address:String},}
We want to create a Map<&AssetInfo, Uint128> to record a user's asset balances. To do this we need to implement PrimaryKey on &AssetInfo. Specifically we want to serialize it the following way:
implAssetInfo{pubfnserialize(&self) -> Vec<u8>{letmut bytes = vec![];// for native coins, we prefix the denom with a zero-byte (0x00)// for cw20s, we prefix the contract address with a one-byte (0x01)matchself{AssetInfo::Native{ denom } => {
bytes.push(0);
bytes.extend(denom.as_bytes());}AssetInfo::Cw20{ contract_address } => {
bytes.push(1);
bytes.extend(contract_address.as_bytes());}}
bytes
}}
But this this is inefficient, as the first key (the Val8) is going to be prefixed by its length. The resulting key is two bytes longer (you get an extra 0x00 0x08).
Potential solution
Add a enum variant to Key which takes an owned, variable-length byte array:
The fixed size value types are there to avoid creating arbitrarily sized keys in the first place.
Now, I see the reason for your change. And, we never really measured the performance impact of using a large key by value.
So, I'm OK with introducing this change. It would be good to benchmark the overhead of using a large key value instead of a reference. It's probably negligible, but it would be good to confirm it.
Currently the
Key
type takes either a ref, or a fixed-length byte slice:The drawback of this is that when implementing the
PrimaryKey
trait, we can't use any custom serialization method of which the output is of variable length.Example
Here is an actual use case I've worked on. Consider the following type:
We want to create a
Map<&AssetInfo, Uint128>
to record a user's asset balances. To do this we need to implementPrimaryKey
on&AssetInfo
. Specifically we want to serialize it the following way:And we implement
PrimaryKey
as follows:But this doesn't work! The
bytes
variable goes out of scope at the end of the function, so the returned&bytes
becomes a dangling pointer!Alternatively, we can do something like this:
But this this is inefficient, as the first key (the
Val8
) is going to be prefixed by its length. The resulting key is two bytes longer (you get an extra0x00 0x08
).Potential solution
Add a enum variant to
Key
which takes an owned, variable-length byte array:pub enum Key<'a> { + Owned(Vec<u8>) Ref(&'a [u8]), Val8([u8; 1]), Val16([u8; 2]), Val32([u8; 4]), Val64([u8; 8]), Val128([u8; 16]), }
This way, when implementing
PrimaryKey
we can simply do:The text was updated successfully, but these errors were encountered: