moros 0.12.0

MOROS: Obscure Rust Operating System
Documentation
use crate::api::console::Style;
use crate::api::process::ExitCode;
use crate::api::syscall;
use crate::api::unit::SizeUnit;
use crate::sys;

use core::num::ParseIntError;
use x86_64::PhysAddr;

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
    match *args.get(1).unwrap_or(&"") {
        "d" | "dump" => dump(&args[2..]),
        "u" | "usage" => usage(&args[2..]),
        "f" | "format" => {
            sys::fs::mount_mem();
            sys::fs::format_mem();
            println!("Memory successfully formatted");
            println!("MFS is now mounted to '/'");
            Ok(())
        }
        "-h" | "--help" => {
            help();
            Ok(())
        }
        _ => {
            help();
            Err(ExitCode::UsageError)
        }
    }
}

fn parse_usize(s: &str) -> Result<usize, ParseIntError> {
    if s.starts_with("0x") {
        usize::from_str_radix(&s[2..], 16)
    } else {
        usize::from_str_radix(s, 10)
    }
}

fn dump(args: &[&str]) -> Result<(), ExitCode> {
    if args.len() != 2 {
        return Err(ExitCode::UsageError);
    }
    let addr = parse_usize(args[0]).unwrap();
    let size = parse_usize(args[1]).unwrap();
    let phys_addr = PhysAddr::new(addr as u64);
    let virt_addr = sys::mem::phys_to_virt(phys_addr);
    let buf = unsafe {
        core::slice::from_raw_parts(virt_addr.as_ptr(), size)
    };
    syscall::write(1, buf);
    Ok(())
}

fn usage(args: &[&str]) -> Result<(), ExitCode> {
    let mut unit = SizeUnit::None;
    for arg in args {
        match *arg {
            "-b" | "--binary-size" => {
                unit = SizeUnit::Binary;
            }
            "-d" | "--decimal-size" => {
                unit = SizeUnit::Decimal;
            }
            "-h" | "--help" => {
                help_usage();
                return Ok(());
            }
            _ => {
                help_usage();
                return Err(ExitCode::Failure);
            }
        }
    }
    let size = sys::mem::memory_size();
    let used = sys::mem::memory_used();
    let free = size - used;
    let width = [size, used, free].iter().fold(0, |acc, num|
        core::cmp::max(acc, unit.format(*num).len())
    );
    let color = Style::color("aqua");
    let reset = Style::reset();
    println!(
        "{}size:{} {:>width$}",
        color,
        reset,
        unit.format(size),
        width = width
    );
    println!(
        "{}used:{} {:>width$}",
        color,
        reset,
        unit.format(used),
        width = width
    );
    println!(
        "{}free:{} {:>width$}",
        color,
        reset,
        unit.format(free),
        width = width
    );
    Ok(())
}

fn help_usage() {
    let csi_option = Style::color("aqua");
    let csi_title = Style::color("yellow");
    let csi_reset = Style::reset();
    println!(
        "{}Usage:{} memory usage {}<options>{}",
        csi_title, csi_reset, csi_option, csi_reset
    );
    println!();
    println!("{}Options:{}", csi_title, csi_reset);
    println!(
        "  {0}-b{1}, {0}--binary-size{1}   Use binary size",
        csi_option, csi_reset
    );
}

fn help() {
    let csi_option = Style::color("aqua");
    let csi_title = Style::color("yellow");
    let csi_reset = Style::reset();
    println!(
        "{}Usage:{} memory {}<command>{}",
        csi_title, csi_reset, csi_option, csi_reset
    );
    println!();
    println!("{}Commands:{}", csi_title, csi_reset);
    println!(
        "  {}dump <addr> <size>{}   Dump memory", csi_option, csi_reset
    );
    println!(
        "  {}format{}               Format RAM disk", csi_option, csi_reset
    );
    println!(
        "  {}usage{}                List memory usage", csi_option, csi_reset
    );
}