csx64 0.1.2

An Intel-style x64 assembler and executor.
Documentation
use crate::common::serialization::*;
use crate::common::*;
use crate::asm::*;
use crate::exec::*;
use crate::exec::fs::*;

use std::io::Cursor;
use std::sync::{Arc, Mutex};

fn serialize_deserialize<T>(thing: &T) -> T where T: BinaryRead + BinaryWrite {
    let mut f = vec![];
    thing.bin_write(&mut f).unwrap();
    T::bin_read(&mut f.as_slice()).unwrap()
}

macro_rules! assert_impl {
    ($t:ty : $r:tt $(+ $rr:tt)*) => {{
        fn f<T: $r $(+ $rr)*>(){}
        f::<$t>()
    }}
}

macro_rules! asm_unwrap_link {
    ([$lib:expr] $($asm:expr),* => $entry:expr) => {{
        let src: Vec<&str> = vec![$($asm),*];
        let mut input: Vec<(String, ObjectFile)> = $lib;
        for (i, src) in src.into_iter().enumerate() {
            let obj = assemble(&format!("file{}.asm", i), &mut src.as_bytes(), Default::default()).unwrap();
            input.push((format!("file{}.o", i), serialize_deserialize(&obj)));
        }
        link(input, $entry)
    }};
    ($($asm:expr),*) => { asm_unwrap_link!([vec![]] $($asm),* => None) };
    (std $($asm:expr),*) => { asm_unwrap_link!([stdlib()] $($asm),* => Some(("start", "main"))) };
}
macro_rules! asm_unwrap_link_unwrap {
    ([$lib:expr] $($asm:expr),* => $entry:expr) => { serialize_deserialize(&asm_unwrap_link!([$lib] $($asm),* => $entry).unwrap()) };
    ($($asm:expr),*) => { serialize_deserialize(&asm_unwrap_link!($($asm),*).unwrap()) };
    (std $($asm:expr),*) => { serialize_deserialize(&asm_unwrap_link!(std $($asm),*).unwrap()) };
}

fn setup_standard_memory_streams(e: &mut Emulator) -> (Arc<Mutex<MemoryFile>>, Arc<Mutex<MemoryFile>>, Arc<Mutex<MemoryFile>>) {
    let stdin = Arc::new(Mutex::new(MemoryFile { content: Cursor::new(vec![]), readable: true, writable: false, seekable: false, appendonly: false, interactive: true }));
    let stdout = Arc::new(Mutex::new(MemoryFile { content: Cursor::new(vec![]), readable: false, writable: true, seekable: false, appendonly: false, interactive: false }));
    let stderr = Arc::new(Mutex::new(MemoryFile { content: Cursor::new(vec![]), readable: false, writable: true, seekable: false, appendonly: false, interactive: false }));
    e.files.handles[0] = Some(stdin.clone());
    e.files.handles[1] = Some(stdout.clone());
    e.files.handles[2] = Some(stderr.clone());
    (stdin, stdout, stderr)
}

mod asm_error_tests;
mod lnk_error_tests;
mod exe_tests;
mod exe_syscall_tests;
mod stdlib_tests;
mod stdio_tests;

#[test]
fn test_send_sync() {
    assert_impl!(ObjectFile: Send + 'static);
    assert_impl!(Executable: Send + 'static);
    assert_impl!(Emulator: Send + 'static);
}