mintrt 0.1.0

Security-featured runtime for lua.
//     <<*>> Revenge of snowflake.
//     -^v-  SASWE
//     @ This source code is licensed under a dual license model:
//       1. MPL-2.0 for non-commercial use only
//       2. Commercial License for commercial use
//       See LICENSE and LICENSE_COMMERCIAL files for details.
use mlua::{Lua, Table};
use std::io::{self, BufRead, Write};
use std::sync::{Arc, Mutex};

/// 消息传输管理器
/// 负责处理标准输入输出与 Lua 运行时之间的消息传递
pub struct TransmitManager {
    // 存储从 stdin 接收的消息队列
    message_queue: Arc<Mutex<Vec<String>>>,
    // 用于从 stdin 读取线程
    reader_handle: Option<std::thread::JoinHandle<()>>,
}

impl TransmitManager {
    /// 创建新的传输管理器实例
    pub fn new() -> Self {
        let message_queue = Arc::new(Mutex::new(Vec::new()));
        
        // 克隆引用用于 stdin 读取线程
        let queue_clone = Arc::clone(&message_queue);
        
        // 启动后台线程持续读取 stdin
        let reader_handle = Some(std::thread::spawn(move || {
            let stdin = io::stdin();
            let mut handle = stdin.lock();
            let mut buffer = String::new();
            
            loop {
                buffer.clear();
                match handle.read_line(&mut buffer) {
                    Ok(0) => {
                        // EOF 到达
                        eprintln!("[TRANSMIT] stdin EOF");
                        break;
                    }
                    Ok(_) => {
                        // 读取到一行数据,根据平台自动处理换行符
                        // Windows: CRLF (\r\n), Unix/Linux: LF (\n)
                        let line = buffer.trim_end_matches('\n').trim_end_matches('\r').to_string();
                        // 只处理以 TOSCRIPT 开头的消息
                        if line.starts_with("TOSCRIPT:") {
                            // 移除 TOSCRIPT:前缀,只保留实际消息内容
                            let message = line.strip_prefix("TOSCRIPT:").unwrap().to_string();
                            if !message.is_empty() {
                                eprintln!("[TRANSMIT] 接收到消息:{}", message);
                                let mut queue = queue_clone.lock().unwrap();
                                queue.push(message);
                            }
                        } else {
                            eprintln!("[TRANSMIT] 忽略非 TOSCRIPT 消息:{}", line);
                        }
                    }
                    Err(e) => {
                        eprintln!("[TRANSMIT] 读取 stdin 错误:{}", e);
                        break;
                    }
                }
            }
        }));
        
        TransmitManager {
            message_queue,
            reader_handle,
        }
    }
    
    /// 获取下一条消息(非阻塞)
    /// 如果没有消息则返回 None
    pub fn get_message(&self) -> Option<String> {
        let mut queue = self.message_queue.lock().unwrap();
        if queue.is_empty() {
            None
        } else {
            Some(queue.remove(0))
        }
    }
    
    /// 获取所有可用消息(非阻塞)
    pub fn get_all_messages(&self) -> Vec<String> {
        let mut queue = self.message_queue.lock().unwrap();
        std::mem::take(&mut *queue)
    }
    
    /// 等待并获取消息(阻塞,带超时)
    /// timeout_ms: 超时时间(毫秒),None 表示无限等待
    pub fn wait_for_message(&self, timeout_ms: Option<u64>) -> Option<String> {
        let start = std::time::Instant::now();
        
        loop {
            {
                let mut queue = self.message_queue.lock().unwrap();
                if !queue.is_empty() {
                    return Some(queue.remove(0));
                }
            }
            
            // 检查是否超时
            if let Some(timeout) = timeout_ms {
                if start.elapsed() >= std::time::Duration::from_millis(timeout) {
                    return None;
                }
            }
            
            // 短暂休眠避免 CPU 占用过高
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }
    
    /// 发送消息到 stdout(以 SWMSG 前缀标识)
    /// 这会被 runtime.rtmsg.send(...) 调用
    pub fn send_message(&self, message: &str) -> io::Result<()> {
        let stdout = io::stdout();
        let mut handle = stdout.lock();
        
        // 写入 SWMSG 前缀和消息
        writeln!(handle, "SWMSG:{}", message)?;
        handle.flush()?;
        
        eprintln!("[TRANSMIT] 发送消息:{}", message);
        Ok(())
    }
    
    /// 初始化 Lua API,暴露给 Lua 脚本使用
    /// 创建 runtime.rtmsg 表,包含 get、get_all、send、wait 方法
    pub fn setup_lua_api(&self, lua: &Lua, runtime_table: &Table) -> Result<(), mlua::Error> {
        let transmit_manager = Arc::clone(&self.message_queue);
        
        // 创建 rtmsg 表
        let rtmsg = lua.create_table()?;
        
        // rtmsg.get() - 获取单条消息
        let queue_get = Arc::clone(&transmit_manager);
        rtmsg.set("get", lua.create_function(move |_, _: ()| -> Result<Option<String>, mlua::Error> {
            let mut queue = queue_get.lock().unwrap();
            if queue.is_empty() {
                Ok(None)
            } else {
                Ok(Some(queue.remove(0)))
            }
        })?)?;
        
        // rtmsg.get_all() - 获取所有消息
        let queue_get_all = Arc::clone(&transmit_manager);
        rtmsg.set("get_all", lua.create_function(move |_, _: ()| -> Result<Vec<String>, mlua::Error> {
            let mut queue = queue_get_all.lock().unwrap();
            Ok(std::mem::take(&mut *queue))
        })?)?;
        
        // rtmsg.wait(timeout_ms) - 等待消息(可选超时)
        let queue_wait = Arc::clone(&transmit_manager);
        rtmsg.set("wait", lua.create_function(move |_, timeout_ms: Option<u64>| -> Result<Option<String>, mlua::Error> {
            let start = std::time::Instant::now();
            
            loop {
                {
                    let mut queue = queue_wait.lock().unwrap();
                    if !queue.is_empty() {
                        return Ok(Some(queue.remove(0)));
                    }
                }
                
                // 检查是否超时
                if let Some(timeout) = timeout_ms {
                    if start.elapsed() >= std::time::Duration::from_millis(timeout) {
                        return Ok(None);
                    }
                }
                
                // 短暂休眠
                std::thread::sleep(std::time::Duration::from_millis(10));
            }
        })?)?;
        
        // rtmsg.send(message) - 发送消息到 stdout
        rtmsg.set("send", lua.create_function(|_, message: String| -> Result<(), mlua::Error> {
            let stdout = io::stdout();
            let mut handle = stdout.lock();
            
            writeln!(handle, "SWMSG:{}", message)
                .map_err(|e| mlua::Error::RuntimeError(format!("发送消息失败:{}", e)))?;
            handle.flush()
                .map_err(|e| mlua::Error::RuntimeError(format!("刷新输出失败:{}", e)))?;
            
            eprintln!("[TRANSMIT] Lua 发送消息:{}", message);
            Ok(())
        })?)?;
        
        // 将 rtmsg 设置为 runtime 的子表
        runtime_table.set("rtmsg", rtmsg)?;
        
        Ok(())
    }
}

impl Default for TransmitManager {
    fn default() -> Self {
        Self::new()
    }
}

/// 初始化传输模块并设置 Lua API
/// 这个函数应该在 runtime.rs 中被调用
pub fn init_transmit(lua: &Lua, runtime_table: &Table) -> Result<Arc<TransmitManager>, mlua::Error> {
    let manager = TransmitManager::new();
    manager.setup_lua_api(lua, runtime_table)?;
    Ok(Arc::new(manager))
}