tail_core 0.1.0

Core library for the Tail operating system
Documentation
// Copyright 2025, TAIL OS. All Rights Reserved.
//
// You must obtain a written license from and pay applicable license fees to TAIL OS
// before you may reproduce, modify, or distribute this software, or any work that
// includes all or part of this software.
//
// Free development licenses are available for evaluation, research, and non-commercial
// purposes, which may include access to the source code under these terms. Redistribution
// or commercial use without a license is strictly prohibited.
//
// This file may contain contributions from others. Please review this entire file for
// other proprietary rights or license notices, as well as the TAIL OS License Guide at
// https://tail-os.com/license-guide/ for more information.
//
// For licensing inquiries, visit https://tail-os.com or email license@tail-os.com.


use core::iter::Iterator;

/*
 * RUST core crate is built on the assumptions of following symbols exist
 */

#[no_mangle]
pub unsafe extern "C" fn memset(dest: *mut u8, val: u8, count: usize) -> *mut u8 {
    for i in 0..count {
        *dest.offset(i as isize) = val;
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.add(i) = *src.add(i);
        i += 1;
    }
    dest
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.add(i);
        let b = *s2.add(i);
        if a != b {
            return a as i32 - b as i32;
        }
        i += 1;
    }
	return 0;
}

#[no_mangle]
fn memmove(dest: *mut u8, src: *const u8, n: usize) {
    unsafe {
        if src < dest {
            // Copy from the end of the buffer to avoid overwriting
            // any data in the overlapping region
            for i in (0..n).rev() {
                *dest.add(i) = *src.add(i);
            }
        } else {
            // Copy from the beginning of the buffer
            for i in 0..n {
                *dest.add(i) = *src.add(i);
            }
        }
    }
}

#[no_mangle]
fn strlen(s: *const u8) -> usize {
    let mut len = 0;
    unsafe {
        while *s.add(len) != 0 {
            len += 1;
        }
    }
    len
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_memset() {
        let mut buf = [0u8; 10];
        unsafe {
            memset(buf.as_mut_ptr(), 0xff, buf.len());
        }
        assert_eq!(buf, [0xff; 10]);
    }

    #[test]
    fn test_memcpy() {
        let mut src = [1u8, 2, 3, 4, 5];
        let mut dst = [0u8; 5];
        unsafe {
            memcpy(dst.as_mut_ptr(), src.as_ptr(), src.len());
        }
        assert_eq!(src, dst);
    }

    #[test]
    fn test_memcmp() {
        let a = [1u8, 2, 3, 4, 5];
        let b = [1u8, 2, 3, 4, 5];
        let c = [1u8, 2, 3, 4, 6];
        unsafe {
            assert_eq!(memcmp(a.as_ptr(), b.as_ptr(), a.len()), 0);
            assert_eq!(memcmp(a.as_ptr(), c.as_ptr(), a.len()), -1);
        }
    }

    #[test]
    fn test_memmove() {
        let mut buf = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        unsafe {
            memmove(buf.as_mut_ptr().offset(3), buf.as_ptr(), 5);
        }
        assert_eq!(buf, [1, 2, 3, 1, 2, 3, 4, 5, 9, 10]);
    }

    #[test]
    fn test_strlen() {
        let s = b"hello world\0";
        unsafe {
            assert_eq!(strlen(s.as_ptr()), 11);
        }
    }
}