osmpbf_parser/
lib.rs

1#![doc=include_str!("../readme.md")]
2use quick_protobuf::{MessageRead,Reader};
3use std::io::{Read,Seek,SeekFrom};
4
5pub mod proto;
6pub use proto::fileformat::{Blob,BlobHeader};
7mod decode;
8pub mod element;
9pub use element::{Element,Info,Node,Way,Relation,Member,MemberType};
10mod scan;
11pub use scan::{Scan,ScanTable};
12mod scan_bytes;
13
14pub type Error = Box<dyn std::error::Error+Send+Sync+'static>;
15
16pub struct Parser<F: Read+Seek> {
17  handle: Box<F>,
18}
19
20impl<F> Parser<F> where F: Read+Seek {
21  pub fn new(handle: Box<F>) -> Self {
22    Self { handle }
23  }
24  pub fn read_fileblock(&mut self, offset: u64) -> Result<(u64,BlobHeader,Blob),Error> {
25    let (s,blob_header) = self.read_blob_header(offset)?;
26    let blob = self.read_blob(offset + s, blob_header.datasize as usize)?;
27    Ok((s + blob_header.datasize as u64, blob_header, blob))
28  }
29  pub fn read_blob_header(&mut self, offset: u64) -> Result<(u64,BlobHeader),Error> {
30    let mut len_buf = [0,0,0,0];
31    self.handle.seek(SeekFrom::Start(offset))?;
32    self.handle.read_exact(&mut len_buf)?;
33    let len = u32::from_be_bytes(len_buf) as usize;
34    self.handle.seek(SeekFrom::Start(offset+4))?;
35    let mut buf = vec![0u8;len];
36    self.handle.read_exact(&mut buf)?;
37    let mut reader = Reader::from_bytes(buf);
38    let blob_header = reader.read(BlobHeader::from_reader)?;
39    Ok(((len+4) as u64, blob_header))
40  }
41  pub fn read_blob(&mut self, offset: u64, len: usize) -> Result<Blob,Error> {
42    self.handle.seek(SeekFrom::Start(offset))?;
43    let mut buf = vec![0u8;len];
44    self.handle.read_exact(&mut buf)?;
45    let mut reader = Reader::from_bytes(buf);
46    let blob = reader.read(Blob::from_reader)?;
47    Ok(blob)
48  }
49  pub fn read(&mut self, offset: u64) -> Result<(u64,Vec<element::Element>),Error> {
50    let (len,_blob_header,blob) = self.read_fileblock(offset)?;
51    if offset == 0 { // header
52      Ok((len, vec![]))
53    } else {
54      Ok((len, blob.decode_primitive()?.decode()))
55    }
56  }
57}