#buf-reader #async-std #extension #file #prelude #chunks #predicate

async_buf_reader_utils

为 async-std crate 的 BufReader 添加附加功能

1 个不稳定版本

0.1.0 2019 年 12 月 22 日

#1728 in 异步

Apache-2.0/MIT

16KB
240

async_buf_reader_utils

该 crate 的目的是为异步 BufReader 实现添加附加功能。

要将附加方法添加到异步 BufReader,只需将其添加到您的模块中

use async_buf_reader_utils::prelude::*;

方法

buf_reader.read_until_index_found(&mut predicate, &mut fillable).await

    fn read_until_index_found<'a, F>(
        &'a mut self,
        predicate_found_index: &'a mut F,
        buf: &'a mut Vec<u8>,
    ) -> ReadChunkUntilIndexFoundFuture<'a, Self, F> 

示例

本示例的目标是加载一个文本文件,并异步地找到给定组中直到第 4 个逗号之前的一组字符。

如果输入文本文件是

1,50,0,3,17,1,212,3,1,3,4,3,1,5

我们希望能够返回

> 1,50,0,3,
> 17,1,212,3,
> 1,3,4,3,
> 1,5

以下是使用 async read_until_index_found 解决此问题的业务逻辑

      fn main() {
        let _result: Result<(), String> = async_std::task::block_on(async {
        
            use async_buf_reader_utils::prelude::*;
            use async_std::{fs::File, io::BufReader};

            // Path to file you want to read asynchronously
            let str_path = "./data/file.txt";

            // Async load file (you can optionally use method with_capacity to limit how 
            // much async-std BufReader bytes are loaded while reading which is useful in memory sensative environments)
            let mut buf = BufReader::with_capacity(12, File::open(&str_path).await.expect("should have opened file"));
            
            let mut comma_count: usize = 0;
            let mut last_comma_idx = None;
            let mut fillable = vec![];

            // Our predicate closure is our business logic,
            // where we are trying to capture all characters up to
            // the 4th comma, remembering that a regex won't be as useful here
            // because our predicate will be called for every loaded chunk
            // of data returned by our async BufReader, so a desired match 
            // might stretch across two different strings provided to the predicate.

            // Once we've reached the 4th comma, return the index via Some(index) and reset
            // our counters, otherwise return None to indicate we are still searching.
            let mut predicate = |str_data: &str|->Option<usize>{
                // println!("in predicate {:?}", str_data);
                last_comma_idx = str_data.bytes().enumerate().find_map(|(i, x)| {
                    if x == b','{
                        comma_count += 1;
                    }
                    if comma_count == 4 {
                        Some(i)
                    }
                    else{
                        None
                    }
                });
                // println!("cur comma idx {:?}", last_comma_idx);
                if let Some(idx) = last_comma_idx {
                    last_comma_idx = None;
                    comma_count = 0;
                    Some(idx)
                }else{
                    None
                }
            };

            // Start our async while loop passing our predicate and buffer to read_until_index_found,
            // so our loop will continue returning the chunks of strings that are resulting
            // from the returned indices in our predicate.
            while let Ok(Some(_)) = buf.read_until_index_found(&mut predicate, &mut fillable).await {
                println!("in while await loop {:?}", str::from_utf8(&fillable).unwrap());
                fillable.clear();
            }
            Ok(())
        });
      }

依赖关系

~6–18MB
~208K SLoC