Read + Seek trait passing to callback


In using Rust for another real world tool:

I have an impl called DatFile which takes a type that must implement Read and Seek. The purpose of the DatFile is to work on files or in memory data that is a custom BTree format. The visit_all function within the DatFile implementation successfully traverses this BTree, The abbreviated code is as follows:

pub struct DatFile<'a, RS: 'a + Read + Seek> {
	file: &'a mut RS,
	header: DatHeader

impl<'a, RS> DatFile<'a, RS> 
	where RS: 'a + Read + Seek
  fn visit_all(
    		&mut self, 
    		f: &mut dyn FnMut(&BtreeDataEntryPostTod) ->  Result<()>)
    		-> Result<()> 
    		let root_ofs = self.header.btree_ofs()? as u64;
    		self.visit_block(root_ofs, f)

	fn visit_block(
		&mut self, 
		offset: u64, 
		f: &mut dyn FnMut(&BtreeDataEntryPostTod) ->  Result<()>
           -> Result<()> 
		let block_size = self.header.block_size()? as usize;
		let node: BtreeNode;
			let mut block = BlockList::new(self.file, block_size);
			node = BtreeNode::load(&mut block)?;
		println!("Entry count {}", node.entry_count);
		for x in 0..node.entry_count as usize {
			if !node.is_leaf() {
				self.visit_block(node.branches[x] as u64, f)?
			match node.data_entries[x] {
				BtreeDataEntry::PostTod(e) => {
				_ => Err(Error::Str("Expecting postTod"))

In the code above the parameter f is some callback, and can be a closure with context. In particular I want f to be able to operate on the same file used for iteration. i.e. self.f which is passed to visit_block, which calls the FnMut called f, with an entry of type BtreeDataEntry::PostTod. The function f passed to visit_all (and visit_block) wants to futher read and seek the file as appropriate, but of course it cannot reborrow self.f as mutable again, therefore I am looking into sensible solutions.Note that the work that the callback f does. e.g. moving the file pointer, should not affect the main iteration of visit_all. So I have the following ideas:

  1. Somehow take a Read + Seek on construction of DatFile, and produce another object that has independant seek position so that it can be passed to the callback. (I don't believe this is possible, even at an os level)
  2. Pass into DatFile two Read + Seek objects, that are essentially the same file, or memory cursor, but would have independent file (seek) positions.
  3. Pass into the FnMut callback function a parameter which is mutable "file" used in visit_block, and record the current seek offset before performing any IO, and restore it before exit, so as to preserve the file position.
    2a. As above but make a wrapper to save/restore the file offset.
  4. Something else.

Any thoughts would be welcome.

I'd probably do that. Unless you can otherwise know where to seek for the next read. E.g. from the code you've included, it looks like you're already doing an absolute seek before any block reads. (But the call to self.visit_block(root_ofs, f) doesn't include the offset parameter that is in the definition.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.