use core::mem; const WORD_SIZE: usize = mem::size_of::<usize>(); /// Memcpy /// /// Copy N bytes of memory from one location to another. /// /// This faster implementation works by copying bytes not one-by-one, but in /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). #[no_mangle] pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { let n_usize: usize = n/WORD_SIZE; // Number of word sized groups let mut i: usize = 0; // Copy `WORD_SIZE` bytes at a time let n_fast = n_usize*WORD_SIZE; while i < n_fast { *((dest as usize + i) as *mut usize) = *((src as usize + i) as *const usize); i += WORD_SIZE; } // Copy 1 byte at a time while i < n { *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); i += 1; } dest } /// Memmove /// /// Copy N bytes of memory from src to dest. The memory areas may overlap. /// /// This faster implementation works by copying bytes not one-by-one, but in /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). #[no_mangle] pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { if src < dest as *const u8 { let n_usize: usize = n/WORD_SIZE; // Number of word sized groups let mut i: usize = n_usize*WORD_SIZE; // Copy `WORD_SIZE` bytes at a time while i != 0 { i -= WORD_SIZE; *((dest as usize + i) as *mut usize) = *((src as usize + i) as *const usize); } let mut i: usize = n; // Copy 1 byte at a time while i != n_usize*WORD_SIZE { i -= 1; *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); } } else { let n_usize: usize = n/WORD_SIZE; // Number of word sized groups let mut i: usize = 0; // Copy `WORD_SIZE` bytes at a time let n_fast = n_usize*WORD_SIZE; while i < n_fast { *((dest as usize + i) as *mut usize) = *((src as usize + i) as *const usize); i += WORD_SIZE; } // Copy 1 byte at a time while i < n { *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); i += 1; } } dest } /// Memset /// /// Fill a block of memory with a specified value. /// /// This faster implementation works by setting bytes not one-by-one, but in /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). #[no_mangle] pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { let c: usize = mem::transmute([c as u8; WORD_SIZE]); let n_usize: usize = n/WORD_SIZE; let mut i: usize = 0; // Set `WORD_SIZE` bytes at a time let n_fast = n_usize*WORD_SIZE; while i < n_fast { *((dest as usize + i) as *mut usize) = c; i += WORD_SIZE; } let c = c as u8; // Set 1 byte at a time while i < n { *((dest as usize + i) as *mut u8) = c; i += 1; } dest } /// Memcmp /// /// Compare two blocks of memory. /// /// This faster implementation works by comparing bytes not one-by-one, but in /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). #[no_mangle] pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { let n_usize: usize = n/WORD_SIZE; let mut i: usize = 0; let n_fast = n_usize*WORD_SIZE; while i < n_fast { let a = *((s1 as usize + i) as *const usize); let b = *((s2 as usize + i) as *const usize); if a != b { let n: usize = i + WORD_SIZE; // Find the one byte that is not equal while i < n { let a = *((s1 as usize + i) as *const u8); let b = *((s2 as usize + i) as *const u8); if a != b { return a as i32 - b as i32; } i += 1; } } i += WORD_SIZE; } while i < n { let a = *((s1 as usize + i) as *const u8); let b = *((s2 as usize + i) as *const u8); if a != b { return a as i32 - b as i32; } i += 1; } 0 }