-
Notifications
You must be signed in to change notification settings - Fork 238
implement Write for uninitialized slices #674
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
base: master
Are you sure you want to change the base?
Conversation
return Err(SliceWriteError::Full); | ||
} | ||
let (a, b) = mem::take(self).split_at_mut(amt); | ||
buf.split_at(amt) |
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.
maybe core::ptr::copy_nonoverlapping has a better chance at getting optimized than iterator loops. Or maybe copy_from_slice but i'm not sure if it's possible to use soundly.
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.
also buf.split_at(amt).0
can be written more readably as buf[..amt]
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.
maybe core::ptr::copy_nonoverlapping has a better chance at getting optimized
agreed, but that requires unsafe code. perhaps we could add that under a feature flag in a future PR?
buf.split_at(amt).0 can be written more readably as buf[..amt]
they behave differently though - .split_at()
splits the lifetime and also works in const
contexts, so i think it is preferred over slicing with []
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 that requires unsafe code
that's not a problem
they behave differently though - .split_at() splits the lifetime and also works in const contexts, so i think it is preferred over slicing with []
the lifetime is not an issue with readonly &[u8]
because aliasing is allowed, and slicing is also allowed in const.
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.
from what i can tell, slicing is not allowed in const contexts.
this example main.rs
using .split_at(n).0
compiles just fine:
const HELLO_WORLD_BYTES: &[u8] = b"hello world";
const HELLO_BYTES_SPLIT_AT: &[u8] = HELLO_WORLD_BYTES.split_at(4).0;
fn main() { panic!() }
================================
PS C:\Users\vivek\git\deletme> cargo rustc -- -Awarnings
Compiling deletme v0.1.0 (C:\Users\vivek\git\deletme)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
whereas this example main.rs
using [..n]
fails to compile:
const HELLO_WORLD_BYTES: &[u8] = b"hello world";
const HELLO_BYTES_SLICE_OPERATOR: &[u8] = &HELLO_WORLD_BYTES[..4];
fn main() { panic!() }
================================
PS C:\Users\vivek\git\deletme> cargo rustc -- -Awarnings
Compiling deletme v0.1.0 (C:\Users\vivek\git\deletme)
error[E0015]: cannot call non-const operator in constants
--> src/main.rs:2:61
|
2 | const HELLO_BYTES_SLICE_OPERATOR: &[u8] = &HELLO_WORLD_BYTES[..4];
| ^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: could not compile `deletme` (bin "deletme") due to 1 previous error
so i think because it supports const contexts, "shrinks" the lifetime, and provides a more simple API, split_at()
should be preferred. fwiw i actually like the readability after getting used to it. i had to deal with const
issues earlier while working in another no_std crate mmstick/numtoa#23
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.
updated to replace safe iterator with unsafe core::ptr::copy_nonoverlapping
in 00346c9
background
similar to how we implement the
Write
traits on&mut [u8]
, we can also add support for&mut [MaybeUninit<u8>]
without usingunsafe
. could be especially useful with core::io::BorrowedBuf.changes
ErrorType
,embedded_io::Write
, &embedded_io_async::Write
for&mut [MaybeUninit<u8>]
&buf[..amt]
withbuf.split_at(amt).0
for consistency (and potential const-context compatibility)