使用解析器组合器箱“nom”来部分读取和解析文件

问题描述 投票:0回答:1

我有一个用例,我只想解析文件的开头直到我决定停止解析。这可以是 4kB 或更多。确切金额尚不清楚。因此无需读取整个文件(例如可以是 100kB)。

我在最常用的名为“nom”的解析器组合器箱中看到的所有内容是,总是解析内存中完整的整块字节或字符。

构建一个动态从文件中读取的自己的数据结构的想法效果不佳,因为我无法覆盖不可变的自引用,如下所示:


  struct MyInput {
   pb : PathBuf,
   read : Box::<dyn Read>,
   filelength : u64,
   current_content : String,
  }


  impl MyInput {
   fn new( pb : PathBuf) -> Self{
    let file = OpenOptions::new().read(true).open(pb.clone()).unwrap();
    let filelength = std::fs::metadata(pb.clone()).unwrap().len();
    let current_content = "".to_string();
    Self { pb, read : Box::new( file), filelength, current_content}
   }
  }

  impl InputLength for MyInput {
   fn input_len(&self) -> usize {
    self.filelength as usize // here I have to tweake something later because char vs. u8
   }
  }

  // here lies the problem

  impl Compare<&str> for MyInput {
    fn compare(&self, t: &str) -> nom::CompareResult { 

      // I cannot fill a cache as I indended to do in self.current_content 
      // because &self is immutable
        todo!()
    }

    fn compare_no_case(&self, t: &str) -> nom::CompareResult {
        todo!()
    }
  }


我的问题还有其他解决方案吗?

parsing rust immutability nom
1个回答
0
投票

我不认为这应该是你的首选解决方案,但是如果你想改变

self
,并且特征的接口只给你一个
&self
,你可以使用内部可变性模式。例如
RefCell
。请阅读本书中的详细解释以了解更多信息。但对于快速片段,您可以使用它。请注意,这会增加跟踪
RefCell
引用数量的少量运行时开销。

use std::cell::RefCell;
use std::ops::DerefMut;

struct Inner {
    pb : PathBuf,
    read : Box::<dyn Read>,
    filelength : u64,
    current_content : String,
}

struct MyInput {
    inner: RefCell<Inner>,
}

impl Compare<&str> for MyInput {
    fn compare(&self, t: &str) -> nom::CompareResult {
        // The call to deref_mut is only to show that you can obtain
        // a mutable reference to inner. 
        let inner: &mut Inner = self.inner.borrow_mut().deref_mut();

        todo!();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.