1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use crate::memory::Memory;
use crate::stack::Stack;
use std::io::{Read, Write};

pub enum ImportError {
    Fatal { message: String },
    NotFound,
}

pub trait Importer {
    fn call(
        &mut self,
        name: &str,
        stack: &mut Stack,
        memory: &mut Memory,
    ) -> Result<(), ImportError>;
}

pub struct DefaultImporter<R: Read, W: Write> {
    stdout: W,
    stdin: R,
}

impl<R: Read, W: Write> Drop for DefaultImporter<R, W> {
    fn drop(&mut self) {
        let _ = self.stdout.flush();
    }
}

impl<R: Read, W: Write> DefaultImporter<R, W> {
    pub fn with_stdio(stdin: R, stdout: W) -> Self {
        Self { stdin, stdout }
    }

    // (func (param i32) (result i32))
    fn putchar(&mut self, stack: &mut Stack) {
        let v: i32 = stack.pop();
        let b = v as u8;
        let ret = match self.stdout.write(&[b]) {
            Ok(_) => b as i32,
            Err(_) => -1, // EOF
        };
        stack.push(ret);
    }

    // (func () (result i32))
    fn getchar(&mut self, stack: &mut Stack) {
        let mut buf = [0u8];
        let v = match self.stdin.read_exact(&mut buf) {
            Ok(()) => buf[0] as i32,
            Err(_) => -1, // EOF
        };
        stack.push(v);
    }

    // (func (param i32 i32 i32) (result i32))
    fn memcpy(&mut self, stack: &mut Stack, memory: &mut Memory) -> Result<(), ImportError> {
        // memcpy(void *dest, void *src, size_t n)
        let size = stack.pop::<i32>() as usize;
        let src_start = stack.pop::<i32>() as usize;
        let dest_i32: i32 = stack.pop();
        let dest_start = dest_i32 as usize;
        let src_end = src_start + size;
        let dest_end = dest_start + size;

        let (dest, src) = if dest_end <= src_start {
            let (dest, src) = memory.data_mut().split_at_mut(src_start);
            (&mut dest[dest_start..dest_end], &mut src[..size])
        } else if src_end <= dest_start {
            let (src, dest) = memory.data_mut().split_at_mut(dest_start);
            (&mut dest[..size], &mut src[src_start..src_end])
        } else {
            return Err(ImportError::Fatal {
                message: format!(
                    "range overwrap on memcpy: src={}..{} and dest={}..{}",
                    src_start, src_end, dest_start, dest_end
                ),
            });
        };

        dest.copy_from_slice(&src);
        stack.push(dest_i32);
        Ok(())
    }
}

impl<R: Read, W: Write> Importer for DefaultImporter<R, W> {
    fn call(
        &mut self,
        name: &str,
        stack: &mut Stack,
        memory: &mut Memory,
    ) -> Result<(), ImportError> {
        match name {
            "putchar" => {
                self.putchar(stack);
                Ok(())
            }
            "getchar" => {
                self.getchar(stack);
                Ok(())
            }
            "memcpy" => self.memcpy(stack, memory),
            _ => Err(ImportError::NotFound),
        }
    }
}