Repository: qdrant/qdrant
File: lib/common/memory/src/mmap_ops.rs (Rust)

Code before:
    madvise::madvise(&mmap, advice.resolve())?;

    Ok(mmap)
}

pub fn open_write_mmap(path: &Path, advice: AdviceSetting, populate: bool) -> io::Result<MmapMut> {
    let file = OpenOptions::new().read(true).write(true).open(path)?;

    let mmap = unsafe { MmapMut::map_mut(&file)? };

    // Populate before advising
    // Because we want to read data with normal advice
    if populate {
        mmap.populate();
    }

    madvise::madvise(&mmap, advice.resolve())?;

    Ok(mmap)
}

/// # Safety
///
/// `data` must have correct alignment and size for `T` and contain correct bit patterns for the type `T`.
pub unsafe fn transmute_from_u8<T>(v: &[u8]) -> &T {
    debug_assert_eq!(v.len(), size_of::<T>());

    debug_assert_eq!(
        v.as_ptr().align_offset(align_of::<T>()),
        0,
        "transmuting byte slice {:p} into {}: \
         required alignment is {} bytes, \
         byte slice misaligned by {} bytes",
        v.as_ptr(),
        std::any::type_name::<T>(),
        align_of::<T>(),
        v.as_ptr().align_offset(align_of::<T>()),
    );

    unsafe { &*v.as_ptr().cast::<T>() }
}

/// # Safety
///
/// T must be a type with stable representation (POD type, Option with niche optimization, etc).
pub unsafe fn transmute_to_u8<T: Sized>(v: &T) -> &[u8] {
    unsafe { std::slice::from_raw_parts(ptr::from_ref::<T>(v).cast::<u8>(), mem::size_of_val(v)) }
}

/// # Safety
///

Review comment (suggestion):
I'd mark these `transumte_*` functions as deprecated. The new code should use `zerocopy` or `bytemuck` instead.

See also: https://github.com/qdrant/qdrant/pull/5297/changes/BASE..be387be795977cfe99fabe77694ba31c66226f32

Code after:
    madvise::madvise(&mmap, advice.resolve())?;

    Ok(mmap)
}

pub fn open_write_mmap(path: &Path, advice: AdviceSetting, populate: bool) -> io::Result<MmapMut> {
    let file = OpenOptions::new().read(true).write(true).open(path)?;

    let mmap = unsafe { MmapMut::map_mut(&file)? };

    // Populate before advising
    // Because we want to read data with normal advice
    if populate {
        mmap.populate();
    }

    madvise::madvise(&mmap, advice.resolve())?;

    Ok(mmap)
}

/// # Safety
///
/// `data` must have correct alignment and size for `T` and contain correct bit patterns for the type `T`.
#[deprecated = "use `bytemuck` or `zerocopy`"]
pub unsafe fn transmute_from_u8<T>(v: &[u8]) -> &T {
    debug_assert_eq!(v.len(), size_of::<T>());

    debug_assert_eq!(
        v.as_ptr().align_offset(align_of::<T>()),
        0,
        "transmuting byte slice {:p} into {}: \
         required alignment is {} bytes, \
         byte slice misaligned by {} bytes",
        v.as_ptr(),
        std::any::type_name::<T>(),
        align_of::<T>(),
        v.as_ptr().align_offset(align_of::<T>()),
    );

    unsafe { &*v.as_ptr().cast::<T>() }
}

/// # Safety
///
/// T must be a type with stable representation (POD type, Option with niche optimization, etc).
#[deprecated = "use `bytemuck` or `zerocopy`"]
pub unsafe fn transmute_to_u8<T: Sized>(v: &T) -> &[u8] {
    unsafe { std::slice::from_raw_parts(ptr::from_ref::<T>(v).cast::<u8>(), mem::size_of_val(v)) }
}