//! Memory-related data structures

pub use abi::mem::{MappingFlags, MappingSource};

#[cfg(any(feature = "rustc-dep-of-std", rust_analyzer))]
mod intrinsics {
    use core::ffi::{c_char, c_void};

    #[no_mangle]
    unsafe extern "C" fn bcmp(p0: *const c_void, p1: *const c_void, len: usize) -> i32 {
        memcmp(p0, p1, len)
    }

    #[no_mangle]
    unsafe extern "C" fn memcmp(p0: *const c_void, p1: *const c_void, len: usize) -> i32 {
        let mut offset = 0;

        if len == 0 {
            return 0;
        }

        while offset < len {
            let c0 = (p0 as *const u8).add(offset).read_volatile();
            let c1 = (p1 as *const u8).add(offset).read_volatile();

            if c0 > c1 {
                return (c0 - c1) as i32;
            } else if c0 < c1 {
                return -((c1 - c0) as i32);
            }

            offset += 1;
        }

        0
    }

    #[no_mangle]
    pub unsafe extern "C" fn memcpy(p0: *mut c_void, p1: *const c_void, len: usize) -> *mut c_void {
        compiler_builtins::mem::memcpy(p0 as _, p1 as _, len) as _
    }

    #[no_mangle]
    unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
        compiler_builtins::mem::memmove(dst as _, src as _, n) as _
    }

    #[no_mangle]
    unsafe extern "C" fn memset(dst: *mut c_void, val: i32, len: usize) -> *mut c_void {
        let mut offset = 0;
        while offset < len {
            (dst as *mut u8).add(offset).write_volatile(val as u8);
            offset += 1;
        }
        dst
    }

    #[no_mangle]
    unsafe extern "C" fn strlen(mut s: *mut c_char) -> usize {
        if s.is_null() {
            return 0;
        }
        let mut len = 0;
        while s.read() != 0 {
            len += 1;
            s = s.add(1);
        }
        len
    }
}
