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

[WIP] Removed code taken from core, using those features instead #496

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 0 additions & 186 deletions src/de/impl_core.rs

This file was deleted.

73 changes: 70 additions & 3 deletions src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,15 +466,15 @@ where
let res = unsafe { ptr.read() };
Ok(res)
} else {
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
let result = try_collect_into_array(&mut (0..N).map(|_| {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
T::decode(decoder)
}));
}))?;

// result is only None if N does not match the values of `(0..N)`, which it always should
// So this unwrap should never occur
result.unwrap()
Ok(unsafe { result.unwrap_unchecked() })
}
}
}
Expand Down Expand Up @@ -626,3 +626,70 @@ const UTF8_CHAR_WIDTH: [u8; 256] = [
const fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
}

// Taken from https://github.com/rust-lang/rust/blob/06a1c14d52a8482a33416c21b320970cab80cccc/library/core/src/array/mod.rs#L792
// and slightly modified
fn try_collect_into_array<I, E, T, const N: usize>(iter: &mut I) -> Result<Option<[T; N]>, E>
where
I: Iterator<Item = Result<T, E>>,
{
use core::mem::MaybeUninit;

if N == 0 {
// SAFETY: An empty array is always inhabited and has no validity invariants.
return unsafe { Ok(Some(core::mem::zeroed())) };
}

struct Guard<'a, T, const N: usize> {
array_mut: &'a mut [MaybeUninit<T>; N],
initialized: usize,
}

impl<T, const N: usize> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);

// SAFETY: this slice will contain only initialized objects.
unsafe {
core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
self.array_mut.get_unchecked_mut(..self.initialized),
));
}
}
}

let mut array = MaybeUninit::uninit_array::<N>();
let mut guard = Guard {
array_mut: &mut array,
initialized: 0,
};

for item in iter {
let item = item?;
// SAFETY: `guard.initialized` starts at 0, is increased by one in the
// loop and the loop is aborted once it reaches N (which is
// `array.len()`).
unsafe {
guard
.array_mut
.get_unchecked_mut(guard.initialized)
.write(item);
}
guard.initialized += 1;

// Check if the whole array was initialized.
if guard.initialized == N {
core::mem::forget(guard);

// SAFETY: the condition above asserts that all elements are
// initialized.
let out = unsafe { MaybeUninit::array_assume_init(array) };
return Ok(Some(out));
}
}

// This is only reached if the iterator is exhausted before
// `guard.initialized` reaches `N`. Also note that `guard` is dropped here,
// dropping all already initialized elements.
Ok(None)
}
1 change: 0 additions & 1 deletion src/de/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Decoder-based structs and traits.

mod decoder;
mod impl_core;
mod impl_tuples;
mod impls;

Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![no_std]
#![warn(missing_docs, unused_lifetimes)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![feature(
maybe_uninit_slice,
maybe_uninit_uninit_array,
maybe_uninit_array_assume_init
)]

//! Bincode is a crate for encoding and decoding using a tiny binary
//! serialization strategy. Using it, you can easily go from having
Expand Down