前几篇文章我们完成了如下功能。

    • 请求的生成
    • 请求到通信字符串的转化
    • 通信字符串解析到回复。

    但一个redis-cli肯定会时刻监听来自键盘的输入,并且根据对应的字符串向服务器发出请求,并获取数据。
    我们把实现这个功能的函数名叫 loop_accept_command。
    首先我们得知道这个函数的参数和返回值。由于这个函数的功能已经包含了redis-cli的几乎所有实现,所以它大概不需要参数,也不需要返回值,它不需要和其他数据发生交互了。

    1. async fn loop_accept_command() -> io::Result<()>{
    2. let read = BufReader::new(io::stdin());
    3. let mut lines = read.lines();
    4. while let Some(line) = lines.next().await {
    5. let line = line?;
    6. println!("{}", line);
    7. }
    8. Ok(())
    9. }

    第2.3行通过标准输入构造了一个行迭代器,第4到7行我们通过next获取标准输入中一行字符串,这就是我们要解析的字符串,我们要将这个字符串解析成请求。在这里我们要假设该字符串可能出现的情况。这里做的最大处理就是通过空白字符划分参数。这里大概的解析流程如下。

    • 是否是空白字符,就一直取到空白字符为止,如果是有效字符,就一直取到有效字符,直到输入结束。

    实际代码如下:

    1. pub fn parer_request(i: &str) -> IResult<&str, Request> {
    2. let (i, (vec, _)) = many_till(
    3. delimited(parse_multispace, parse_not_multispace, parse_multispace),
    4. all_consuming(parse_multispace),
    5. )(i)?;
    6. let mut request = Request::new();
    7. vec.iter().for_each(|s| request.add_arg(s));
    8. Ok((i, request))
    9. }

    many_till:会持续解析应用第一参数的解析器,直到第二参数的解析器解析完成。
    现在loop_accept_command的函数如下:

    1. async fn loop_accept_command() -> io::Result<()> {
    2. let read = BufReader::new(io::stdin());
    3. let mut lines = read.lines();
    4. while let Some(line) = lines.next().await {
    5. let line: String = line?;
    6. let (_, request) = request::Request::parer_request(&line).unwrap();
    7. println!("{:?}", request);
    8. }
    9. Ok(())
    10. }