tempest-repl 0.0.1

TempestDB interactive REPL
Documentation
use std::io::{self, BufRead, BufWriter};

use wasm_bindgen::prelude::*;

use crate::stdio::{Stdio, out::RawOut};

#[wasm_bindgen]
extern "C" {
    pub fn wasm_stdin_read_line() -> String;
    pub fn wasm_stdout_write(data: &[u8]);
    pub fn wasm_stderr_write(data: &[u8]);
}

pub struct WasmStdin {
    buf: Vec<u8>,
    pos: usize,
}

impl io::Read for WasmStdin {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let filled = self.fill_buf()?;
        let n = filled.len().min(out.len());
        out[..n].copy_from_slice(&filled[..n]);
        self.consume(n);
        Ok(n)
    }
}

impl io::BufRead for WasmStdin {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        if self.pos >= self.buf.len() {
            wasm_stdout_write(b"\x1b[2K\r>> ");
            let line = wasm_stdin_read_line();
            self.buf = line.into_bytes();
            self.pos = 0;
        }
        Ok(&self.buf[self.pos..])
    }

    fn consume(&mut self, amount: usize) {
        self.pos = (self.pos + amount).min(self.buf.len());
    }
}

pub struct WasmStdout;

impl io::Write for WasmStdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        wasm_stdout_write(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct WasmStderr;

impl io::Write for WasmStderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        wasm_stderr_write(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct WasmStdio {
    stdin: WasmStdin,
    stdout: RawOut<BufWriter<WasmStdout>>,
    stderr: RawOut<BufWriter<WasmStderr>>,
}

impl WasmStdio {
    pub fn new() -> Self {
        Self {
            stdin: WasmStdin {
                buf: Vec::new(),
                pos: 0,
            },
            stdout: RawOut(BufWriter::new(WasmStdout)),
            stderr: RawOut(BufWriter::new(WasmStderr)),
        }
    }
}

impl Stdio for WasmStdio {
    fn stdin(&mut self) -> &mut impl BufRead {
        &mut self.stdin
    }

    fn stdout(&mut self) -> &mut impl io::Write {
        &mut self.stdout
    }

    fn stderr(&mut self) -> &mut impl io::Write {
        &mut self.stderr
    }

    fn push_history(&mut self, _entry: &str) {}
}