A pattern that I see in some packages is that they have FormatReader
struct, and FormatIterator
that handles iteration. In osmpbfreader, struct OsmPbfReader returns OsmObjs as iterator.
XML reader which I use, is pretty clear:
pub struct EventReader<R: Read> {
source: R,
parser: PullParser
}
impl<R: Read> IntoIterator for EventReader<R> {
type Item = Result<XmlEvent>;
type IntoIter = Events<R>;
fn into_iter(self) -> Events<R> {
Events { reader: self, finished: false }
}
}
pub struct Events<R: Read> {
reader: EventReader<R>,
finished: bool
}
(edit: this is not my code, it's xml-rs crate)
I'm trying to implement a wrapper to this, in roder to parse XML and return Osm objects. I need to have both EventReader (it has position
which tells pos in text to report errors), and Events
(it has the iterator proper). But I can't figure out how.
pub struct OsmReader {
er: EventReader<Box<dyn Read>>,
ev: Events<Box<dyn Read>> // iterator over XMLEvents,
// Events implements Iter: next() -> Option<Result<XmlEvent, dyn std::error::Error>>
}
impl OsmReader {
pub fn new(path: String) -> Result<Self, Box<dyn Error>> {
// a wrapper for flat/gzipped/bzipped files
let rd = ...;
let er = EventReader::new(rd);
Ok(OsmReader { er: er, ev: er.into_iter() })
}
}
Error is that {er: er
causes er
to move. Or if I do let ev = er.into_iter()
earlier, this call will cause er
to move ether.
Trying to wrap these in Box
changed nothing:
pub struct OsmReader {
er: Box<EventReader<Box<dyn Read>>>,
ev: Box<Events<Box<dyn Read>>> // iterator over XMLEvents,
// Events implements Iter: next() -> Option<Result<XmlEvent, dyn std::error::Error>>
}
...
let er = Box::new(EventReader::new(rd));
let ev = Box::new((*er).into_iter());
Ok(OsmReader { er: er, ev: ev })
same error:
55 | let ev = Box::new((*er).into_iter());
| ----------- `*er` moved due to this method call
56 | Ok(OsmReader { er: er, ev: ev })
| ^^ value used here after move
I could store just one of them, but this is inconvenient when I implement an iterator, and causes a ton of other code to write (in particular, EventReader
exposes position
, but Events
does not, and EventReader
has next()
but the return type is deeper nested ).
Is there any hope?