#![no_std]
use core::ptr;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memset(dest: *mut u8, value: u8, count: usize) {
let mut ptr = dest;
for _ in 0..count {
unsafe { ptr::write(ptr, value) };
ptr = unsafe { ptr.add(1) };
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
for i in 0..n {
let a = unsafe { ptr::read(s1.add(i)) };
let b = unsafe { ptr::read(s2.add(i)) };
if a != b {
return a as i32 - b as i32;
}
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, count: usize) {
for i in 0..count {
unsafe { ptr::write(dest.add(i), ptr::read(src.add(i))) };
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, count: usize) {
if dest as usize <= src as usize || dest as usize >= src as usize + count {
for i in 0..count {
unsafe { ptr::write(dest.add(i), ptr::read(src.add(i))) };
}
} else {
for i in (0..count).rev() {
unsafe { ptr::write(dest.add(i), ptr::read(src.add(i))) };
}
}
}
#[cfg(test)]
extern crate std;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memset() {
let mut buf = [0u8; 8];
unsafe { memset(buf.as_mut_ptr(), 0xAA, buf.len()) };
assert!(buf.iter().all(|&b| b == 0xAA));
}
#[test]
fn test_memcmp_equal() {
let a = [1u8, 2, 3, 4];
let b = [1u8, 2, 3, 4];
let res = unsafe { memcmp(a.as_ptr(), b.as_ptr(), a.len()) };
assert_eq!(res, 0);
}
#[test]
fn test_memcmp_unequal() {
let a = [1u8, 2, 3, 4];
let b = [1u8, 2, 4, 4];
let res = unsafe { memcmp(a.as_ptr(), b.as_ptr(), a.len()) };
assert!(res < 0);
let res2 = unsafe { memcmp(b.as_ptr(), a.as_ptr(), a.len()) };
assert!(res2 > 0);
}
#[test]
fn test_memcpy() {
let src = [1u8, 2, 3, 4, 5];
let mut dest = [0u8; 5];
unsafe { memcpy(dest.as_mut_ptr(), src.as_ptr(), src.len()) };
assert_eq!(src, dest);
}
#[test]
fn test_memmove_nonoverlapping() {
let src = [10u8, 20, 30, 40];
let mut dest = [0u8; 4];
unsafe { memmove(dest.as_mut_ptr(), src.as_ptr(), src.len()) };
assert_eq!(src, dest);
}
#[test]
fn test_memmove_overlapping_forward() {
let mut buf = [1u8, 2, 3, 4, 5];
let src = buf.as_ptr();
let dest = unsafe { buf.as_mut_ptr().add(2) };
unsafe { memmove(dest, src, 3) };
assert_eq!(buf, [1, 2, 1, 2, 3]);
}
#[test]
fn test_memmove_overlapping_backward() {
let mut buf = [1u8, 2, 3, 4, 5];
let src = unsafe { buf.as_ptr().add(2) };
let dest = buf.as_mut_ptr();
unsafe { memmove(dest, src, 3) };
assert_eq!(buf, [3, 4, 5, 4, 5]);
}
}