mlua-periphery 1.2.4

A Rust-native implementation of lua-periphery for mlua.
use crate::serial::Serial;
use mlua::Error::RuntimeError;
use mlua::{Error, FromLua, Lua, MultiValue};
use std::str::from_utf8;
use std::time::Duration;

pub(super) fn handle(lua: &Lua, serial: &Serial, arg: MultiValue) -> Result<String, Error> {
    // Read args
    let args: Vec<_> = arg.into_iter().collect();
    let (length, timeout_ms) = {
        if args.is_empty() {
            return Err(RuntimeError("A length <number> arg is required".to_string()));
        }
        let length: usize = usize::from_lua(args[0].clone(), lua)?;
        let timeout_ms = {
            if args.len() >= 2 {
                u64::from_lua(args[1].clone(), lua)?
            } else {
                15_000_u64
            }
        };
        (length, timeout_ms)
    };

    let (bytes_read, buf) = {
        // Configure timeout
        let mut locked_port = serial.port.lock().map_err(|err| RuntimeError(err.to_string()))?;
        locked_port.set_read_timeout(Duration::from_millis(timeout_ms))?;

        // Perform read
        let arr = vec![0_u8; length];
        let mut buf = arr.into_boxed_slice();
        let bytes_read = match locked_port.read(&mut buf) {
            Ok(bytes_read) => Ok(bytes_read),
            Err(e) if e.kind() == std::io::ErrorKind::TimedOut => Ok(0),
            Err(e) => Err(e),
        }?;

        (bytes_read, buf)
    };

    // Prepare response
    let res: &[u8] = &buf[0..bytes_read];
    let str = from_utf8(res)?;
    Ok(str.to_string())
}