tmontaigu / shapefile-rs

Rust library to read & write shapefiles
MIT License
59 stars 19 forks source link

Trying to port to dbase 0.1 - ownership issue on Reader::iter_shapes_and_records_as #16

Closed rfilmyer closed 3 years ago

rfilmyer commented 4 years ago

Hi,

I was trying to see if I could get this crate to work with the newest version of another one of your crates, dbase 0.1.

Although the API has changed I think I was able to figure out how to switch from a dbase::Writer to a dbase::TableWriter.

Unfortunately, I seem to be stuck dealing with some ownership issues - since dbase::Reader isn't Iterator anymore, I had to rewrite iter_shapes_and_records_as to return a dbase::RecordIterator, but I can't figure out how to give something ownership of the dbase::Reader

I wrote my function something like this.

    pub fn iter_shapes_and_records_as<'a, S: ReadableShape>(
        mut self,
    ) -> Result<ShapeRecordIterator<'a, T, S>, Error> {
        let mut dbf_reader = self.dbf_reader.take().ok_or(Error::MissingDbf)?; // Now dbf_reader is owned by the current function
        let dbf_iter = dbf_reader.iter_records(); // but a dbase::RecordIterator only has a reference to it: `&'a mut Reader<T>`
        Ok(ShapeRecordIterator{
            shape_iter: self.iter_shapes_as::<S>(),
            dbf_iter, // thus this is invalid because it "returns a value referencing data owned by the current function"
        })

    }

Sorry if this issue was invalid but I can't figure out of this is an issue with dbase, or if I'm just not writing something correctly.

tmontaigu commented 4 years ago

Well, the issue is in both shapefile & dbase,

For their iter methods, one takes self the other takes &mut self.

In shapefile iter_shapes takes self because the file can be itered only once because iter_shapes does not seek to the start of the records.

In dbase the iter_records should also take self because it has the same behaviour but because one might want to create a TableWriter::from_reader, if the iter_record moves the reader then it becomes impossible to reuse the reader to create its writer without cloning.

The probable easiest way to make them work together would be to make shapfile::Reader::iter_* thake &mut self