//! Utility functionality.
//!
//! The code here is not directly relevant to `takeaway`, but it often proves
//! useful.

use alloc::vec::Vec;
use core::{mem::MaybeUninit, ptr};

mod executor;
pub use executor::block_on;

//----------- crossbeam_utils --------------------------------------------------
//
// '{backoff,cache_padded}.rs' are a vendored subset of the `crossbeam-utils`
// crate (version 0.8.21).

#[cfg(not(feature = "crossbeam-utils"))]
mod backoff;

#[cfg(not(feature = "crossbeam-utils"))]
mod cache_padded;

#[cfg(not(feature = "crossbeam-utils"))]
pub use backoff::Backoff;

#[cfg(not(feature = "crossbeam-utils"))]
pub use cache_padded::CachePadded;

#[cfg(feature = "crossbeam-utils")]
pub use crossbeam_utils::{Backoff, CachePadded};

//----------- extend_vec_from_slice() ------------------------------------------

/// Append elements of a slice to a [`Vec`].
///
/// # Safety
///
/// `slice` must contain initialized elements.  They will be moved out.
pub(crate) unsafe fn extend_vec_from_slice<T>(
    vec: &mut Vec<T>,
    slice: &[MaybeUninit<T>],
) {
    let len = vec.len();
    vec.reserve(slice.len());
    let src = slice;
    let dst = &mut vec.spare_capacity_mut()[..slice.len()];

    // SAFETY: 'src' and 'dst' are readable and writable, respectively.
    unsafe {
        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), slice.len());
    }

    // SAFETY: 'src' contained 'slice.len()' initialized elements.
    unsafe { vec.set_len(len + slice.len()) };
}
