xtap-core-lib 0.5.0

星TAP实验室通用 Rust 基座:跨平台路径/IO/硬件/MCP HTTP 服务/egui 主题与字体(features 按需裁剪)
Documentation
/*
 * shell/dispatch.rs
 * Project: core_lib
 * Description: argv → 运行模式的纯解析路由(无外部依赖)
 *
 * 规则:
 * - 第一个参数为 `serve`  → Mode::Serve,支持 --host / --port 覆盖默认值
 * - 第一个参数为 `gui`    → Mode::Gui(仅 `gui` feature 下存在该分支)
 * - 其余                   → Mode::Command(原样透传,交给 app 的命令处理器)
 */

use super::Mode;

/// serve 模式默认监听地址。
pub const DEFAULT_HOST: &str = "127.0.0.1";
/// serve 模式默认端口。
pub const DEFAULT_PORT: u16 = 9876;

/// 把去掉 argv[0] 后的参数解析成运行 [`Mode`]。
pub fn parse(args: &[String]) -> Mode {
    match args.first().map(String::as_str) {
        Some("serve") => parse_serve(&args[1..]),
        #[cfg(feature = "gui")]
        Some("gui") => Mode::Gui,
        _ => Mode::Command(args.to_vec()),
    }
}

fn parse_serve(rest: &[String]) -> Mode {
    let mut host = DEFAULT_HOST.to_string();
    let mut port = DEFAULT_PORT;
    let mut i = 0;
    while i < rest.len() {
        match rest[i].as_str() {
            "--host" => {
                if let Some(v) = rest.get(i + 1) {
                    host = v.clone();
                    i += 1;
                }
            }
            "--port" => {
                if let Some(v) = rest.get(i + 1) {
                    if let Ok(p) = v.parse::<u16>() {
                        port = p;
                    }
                    i += 1;
                }
            }
            _ => {}
        }
        i += 1;
    }
    Mode::Serve { host, port }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn v(items: &[&str]) -> Vec<String> {
        items.iter().map(|s| s.to_string()).collect()
    }

    #[test]
    fn serve_defaults() {
        match parse(&v(&["serve"])) {
            Mode::Serve { host, port } => {
                assert_eq!(host, DEFAULT_HOST);
                assert_eq!(port, DEFAULT_PORT);
            }
            _ => panic!("expected Serve"),
        }
    }

    #[test]
    fn serve_overrides() {
        match parse(&v(&["serve", "--host", "0.0.0.0", "--port", "8080"])) {
            Mode::Serve { host, port } => {
                assert_eq!(host, "0.0.0.0");
                assert_eq!(port, 8080);
            }
            _ => panic!("expected Serve"),
        }
    }

    #[test]
    fn command_passthrough() {
        match parse(&v(&["search", "foo", "-t", "3"])) {
            Mode::Command(argv) => assert_eq!(argv, v(&["search", "foo", "-t", "3"])),
            _ => panic!("expected Command"),
        }
    }

    #[test]
    fn empty_is_command() {
        match parse(&v(&[])) {
            Mode::Command(argv) => assert!(argv.is_empty()),
            _ => panic!("expected Command"),
        }
    }
}