Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate IntKey #547

Merged
merged 16 commits into from
Nov 15, 2021
Merged

Deprecate IntKey #547

merged 16 commits into from
Nov 15, 2021

Conversation

ueco-jb
Copy link
Contributor

@ueco-jb ueco-jb commented Nov 15, 2021

closes #472
Successor of #503.

Idea is to add very small wrapper, which takes either reference or small value (of limited number of bytes).
References should be used for any slice types, while refs for int types.
It's basically same approach as with IntKey, but instead of wrapping at beginning we do it at the end (in the result).

@ueco-jb ueco-jb mentioned this pull request Nov 15, 2021
@ueco-jb ueco-jb added the enhancement New feature or request label Nov 15, 2021
@ueco-jb ueco-jb marked this pull request as ready for review November 15, 2021 10:02
packages/storage-plus/src/keys.rs Show resolved Hide resolved
.iter()
.map(|e| e.as_ref())
.collect::<Vec<_>>()
.as_slice(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It couldn't, but I used simpler .map:

&k.key().iter().map(Key::as_ref).collect::<Vec<_>>(),

@@ -128,7 +129,7 @@ where

pub fn with_deserialization_function(
top_name: &[u8],
sub_names: &[&[u8]],
sub_names: &[Key],
Copy link
Contributor

@maurolacy maurolacy Nov 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that (for now at least) this Key hasn't leaked to Map and friends.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree very much. I would try hard to hide that from contract developers, even if we use it everywhere in internal APIs. (And they can see it if they try to implement their own PrimaryKey type, but then we self-select for experienced devs)

Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

Left a few comments, but most are my surprise with the changes of the compiler, to auto-reference on eg. match a: &Option<X> and handling equals between [u8; 5] and &[u8].

Both nice and surprising ergonomic improvements. Happy for a link to the Rust upgrade that brought them.

@@ -112,6 +112,22 @@ macro_rules! integer_de {

integer_de!(for i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);

macro_rules! intkey_de {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, cool.. just started commenting how we need both. Then see how we do.

Nice!

@@ -20,15 +22,15 @@ pub(crate) fn may_deserialize<T: DeserializeOwned>(
value: &Option<Vec<u8>>,
) -> StdResult<Option<T>> {
match value {
Some(vec) => Ok(Some(from_slice(&vec)?)),
Some(vec) => Ok(Some(from_slice(vec)?)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think & used to be required by the compiler.
But now it is smarter?

Any idea when this changed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea. One way to check it could be compiling with different versions, and see in which one this started to work. The match is producing a ref, and that ref is being converted to slice without any help. Not sure this wasn't supported earlier...

packages/storage-plus/src/keys.rs Show resolved Hide resolved
Val8([u8; 1]),
Val16([u8; 2]),
Val32([u8; 4]),
Val64([u8; 8]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, how about adding Val128([u8; 16]) I am sure that sooner or later someone will want u128 as a key

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't implement it for 128 bits on purpose. Enums are tagged unions. So, they have the size of their largest element (plus an extra for the tagging).

Adding 128 bits support would double the size of Key to 16 bytes (plus the extra for tagging, which must end up in a 32-bits aligned boundary). So, 20 bytes instead of 12.

And, we are not using 128 int keys anywhere. We can easily add it, if you want. Or we can always add it later, when needed / requested.

}
}

integer_key!(for i8, Val8, u8, Val8, i16, Val16, u16, Val16, i32, Val32, u32, Val32, i64, Val64, u64, Val64);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh? I am a bit lost here with the macros, wouldn't it be:

integer_key!(i8, Val8);
integer_key!(u8, Val8);
integer_key!(i16, Val16);
integer_key!(u16, Val16);
...

Or that for i8 does something magic?

Copy link
Contributor

@maurolacy maurolacy Nov 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the for keyword yes. Sadly, with declarative macros we cannot take the type (i8), obtain the size (8), and build a token (Val8). That's why those are specified twice.

I've heard something like that can be done with procedural macros, though.

type SuperSuffix = Self;

fn key(&self) -> Vec<Key> {
vec![Key::$v(self.to_be_bytes())]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

packages/storage-plus/src/keys.rs Show resolved Hide resolved
@@ -380,7 +491,7 @@ mod test {
let k: K = "hello";
let path = k.key();
assert_eq!(1, path.len());
assert_eq!("hello".as_bytes(), path[0]);
assert_eq!(b"hello", path[0].as_ref());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the compiler has gotten smarter.

packages/storage-plus/src/keys.rs Show resolved Hide resolved
@@ -128,7 +129,7 @@ where

pub fn with_deserialization_function(
top_name: &[u8],
sub_names: &[&[u8]],
sub_names: &[Key],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree very much. I would try hard to hide that from contract developers, even if we use it everywhere in internal APIs. (And they can see it if they try to implement their own PrimaryKey type, but then we self-select for experienced devs)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecate IntKey
3 participants