前几篇文章我们完成了如下功能。
- 请求的生成
- 请求到通信字符串的转化
- 通信字符串解析到回复。
但一个redis-cli肯定会时刻监听来自键盘的输入,并且根据对应的字符串向服务器发出请求,并获取数据。
我们把实现这个功能的函数名叫 loop_accept_command。
首先我们得知道这个函数的参数和返回值。由于这个函数的功能已经包含了redis-cli的几乎所有实现,所以它大概不需要参数,也不需要返回值,它不需要和其他数据发生交互了。
async fn loop_accept_command() -> io::Result<()>{
let read = BufReader::new(io::stdin());
let mut lines = read.lines();
while let Some(line) = lines.next().await {
let line = line?;
println!("{}", line);
}
Ok(())
}
第2.3行通过标准输入构造了一个行迭代器,第4到7行我们通过next获取标准输入中一行字符串,这就是我们要解析的字符串,我们要将这个字符串解析成请求。在这里我们要假设该字符串可能出现的情况。这里做的最大处理就是通过空白字符划分参数。这里大概的解析流程如下。
- 是否是空白字符,就一直取到空白字符为止,如果是有效字符,就一直取到有效字符,直到输入结束。
实际代码如下:
pub fn parer_request(i: &str) -> IResult<&str, Request> {
let (i, (vec, _)) = many_till(
delimited(parse_multispace, parse_not_multispace, parse_multispace),
all_consuming(parse_multispace),
)(i)?;
let mut request = Request::new();
vec.iter().for_each(|s| request.add_arg(s));
Ok((i, request))
}
many_till:会持续解析应用第一参数的解析器,直到第二参数的解析器解析完成。
现在loop_accept_command的函数如下:
async fn loop_accept_command() -> io::Result<()> {
let read = BufReader::new(io::stdin());
let mut lines = read.lines();
while let Some(line) = lines.next().await {
let line: String = line?;
let (_, request) = request::Request::parer_request(&line).unwrap();
println!("{:?}", request);
}
Ok(())
}