-
Notifications
You must be signed in to change notification settings - Fork 59
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
fix: make Serde (de)serialization no_std compatible #337
Conversation
`multihash` v0.19 introduced a regression. It's no longer possible to compile with `no_std` and `serde` feature enabled. This commit fixes that regression. Due to generic_const_exprs not being a thing yet, we need to use unsafe code to provide this functionality. Fixes #336.
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 looks correct as-is, but see my comments.
src/serde.rs
Outdated
// Make sure that the struct allocated continuous memory, as we exploit that fact with the | ||
// `as_slice` and `as_mut_slice()` methods. | ||
let start_first = ptr::addr_of!(buffer.first) as *const u8; | ||
let start_second = ptr::addr_of!(buffer.second) as *const u8; | ||
unsafe { | ||
// This should never happen, hence it's OK to panic. | ||
if start_second.offset_from(start_first) != SIZE_FIRST as isize { | ||
panic!("alignment of the struct is wrong") | ||
} | ||
} |
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 shouldn't be necessary as packed
guarantees this.
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.
But you could consider writing a test to assert this (but I'd avoid doing this at runtime).
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.
Actually, you can static_assertions
to assert that mem::size_of::<Self>() == SIZE_FIRST + SIZE_SECOND
at compile time.
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.
You can also assert tat Self
and [u8]
have the same alignment.
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.
I've tried
const_assert!(mem::size_of::<Self>() == SIZE_FIRST + SIZE_SECOND);
but sadly it cannot be compiled:
> cargo build --no-default-features --features serde
error[E0401]: can't use generic parameters from outer function
--> src/serde.rs:38:38
|
29 | impl<const SIZE_FIRST: usize, const SIZE_SECOND: usize> Buffer<SIZE_FIRST, SIZE_SECOND> {
| ---- `Self` type implicitly declared here, by this `impl`
...
38 | const_assert!(mem::size_of::<Self>() == SIZE_FIRST + SIZE_SECOND);
| ^^^^
| |
| use of generic parameter from outer function
| use a type here instead
error[E0401]: can't use generic parameters from outer function
--> src/serde.rs:38:49
|
29 | impl<const SIZE_FIRST: usize, const SIZE_SECOND: usize> Buffer<SIZE_FIRST, SIZE_SECOND> {
| ---------- const parameter from outer function
...
38 | const_assert!(mem::size_of::<Self>() == SIZE_FIRST + SIZE_SECOND);
| ^^^^^^^^^^ use of generic parameter from outer function
error[E0401]: can't use generic parameters from outer function
--> src/serde.rs:38:62
|
29 | impl<const SIZE_FIRST: usize, const SIZE_SECOND: usize> Buffer<SIZE_FIRST, SIZE_SECOND> {
| ----------- const parameter from outer function
...
38 | const_assert!(mem::size_of::<Self>() == SIZE_FIRST + SIZE_SECOND);
| ^^^^^^^^^^^ use of generic parameter from outer function
For more information about this error, try `rustc --explain E0401`.
error: could not compile `multihash` (lib) due to 3 previous errors
So would you prefer if I remove that run-time check and write a test instead?
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.
I've moved it into a test. Though if anyone has an idea on how to assert it at compile-time, that would even be better.
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.
Ah... yeah, generics. I... don't. But I think a test is probably enough.
Instead move the alignment check into a test. Also remove the `len()` method and use `mem::size_of()` instead.
multihash
v0.19 introduced a regression. It's no longer possible to compile withno_std
andserde
feature enabled. This commit fixes that regression.Due to generic_const_exprs not being a thing yet, we need to use unsafe code to provide this functionality.
Fixes #336.