-
Notifications
You must be signed in to change notification settings - Fork 94
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
BitVec: Improve the encoding and consolidate the implementations #327
Conversation
impl<O: BitOrder, T: BitStore> Encode for BitSlice<T, O> | ||
where | ||
T::Mem: Encode | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This technically is semver breaking, but I would go this route. BitVec
already required the same bound.
In general, the tests don't really look like they test that the bitvec is still being encoded in the same binary format as previously, only that it can be encoded and decoded back and still be equal. Is it worth adding a couple of tests to check that the SCALE encoded bytes are what we expect, too? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A before/after test like James suggests is a good idea to add.
for element in self.domain() { | ||
// Iterate over chunks | ||
for chunk in self.chunks(core::mem::size_of::<T>() * 8) { | ||
let mut element = T::ZERO; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be moved outside the loop perhaps and re-used? Or will the compiler re-use element
anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be wrong. As the last chunk could have less bits than the ones before, we could end up with an element having bits set that should not be set. I mean that should be fixed on the decoding side. However, I also don't see any real performance issue with having the primitive type inside the loop.
The old encode was wrong. It would have lead to decode decoding junk. This is now fixed and the expected encoding format didn't changed. |
Yup, of course in some cases it was broken previously. But it would be nice to have a couple of tests to check that the encoding format is what we are expecting it to be in other places, for example that Actually, I had a play myself and this naive test: #[test]
fn bitvec_u8_encodes_as_expected() {
let cases = vec![
(bitvec![u8, Lsb0; 0, 0, 1, 1].encode(), (Compact(4u32), 0b00001100u8).encode()),
(bitvec![u8, Lsb0; 0, 1, 1, 1].encode(), (Compact(4u32), 0b00001110u8).encode()),
(bitvec![u8, Lsb0; 1, 1, 1, 1].encode(), (Compact(4u32), 0b00001111u8).encode()),
(bitvec![u8, Lsb0; 1, 1, 1, 1, 1].encode(), (Compact(5u32), 0b00011111u8).encode()),
(bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 0].encode(), (Compact(6u32), 0b00011111u8).encode()),
];
for (idx, (actual, expected)) in cases.into_iter().enumerate() {
assert_eq!(actual, expected, "case at index {idx} failed; encodings differ");
}
} seemed to pass equally before and after the change, which gives me some confidence that the SCALE format is identical (of course it could be extended towork with different orderings and store types) :) |
CI is green. |
I added the test. However, it was already ensured that the format didn't changed, because we don't have changed the |
bot merge |
No description provided.