1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#![doc=include_str!("../readme.md")]
use quick_protobuf::{MessageRead,Reader};
use std::io::{Read,Seek,SeekFrom};

pub mod proto;
pub use proto::fileformat::{Blob,BlobHeader};
mod decode;
pub mod element;
pub use element::{Element,Info,Node,Way,Relation,Member,MemberType};
mod scan;
pub use scan::{Scan,ScanTable};
mod scan_bytes;

pub type Error = Box<dyn std::error::Error+Send+Sync+'static>;

pub struct Parser<F: Read+Seek> {
  handle: Box<F>,
}

impl<F> Parser<F> where F: Read+Seek {
  pub fn new(handle: Box<F>) -> Self {
    Self { handle }
  }
  pub fn read_fileblock(&mut self, offset: u64) -> Result<(u64,BlobHeader,Blob),Error> {
    let (s,blob_header) = self.read_blob_header(offset)?;
    let blob = self.read_blob(offset + s, blob_header.datasize as usize)?;
    Ok((s + blob_header.datasize as u64, blob_header, blob))
  }
  pub fn read_blob_header(&mut self, offset: u64) -> Result<(u64,BlobHeader),Error> {
    let mut len_buf = [0,0,0,0];
    self.handle.seek(SeekFrom::Start(offset))?;
    self.handle.read_exact(&mut len_buf)?;
    let len = u32::from_be_bytes(len_buf) as usize;
    self.handle.seek(SeekFrom::Start(offset+4))?;
    let mut buf = vec![0u8;len];
    self.handle.read_exact(&mut buf)?;
    let mut reader = Reader::from_bytes(buf);
    let blob_header = reader.read(BlobHeader::from_reader)?;
    Ok(((len+4) as u64, blob_header))
  }
  pub fn read_blob(&mut self, offset: u64, len: usize) -> Result<Blob,Error> {
    self.handle.seek(SeekFrom::Start(offset))?;
    let mut buf = vec![0u8;len];
    self.handle.read_exact(&mut buf)?;
    let mut reader = Reader::from_bytes(buf);
    let blob = reader.read(Blob::from_reader)?;
    Ok(blob)
  }
  pub fn read(&mut self, offset: u64) -> Result<(u64,Vec<element::Element>),Error> {
    let (len,_blob_header,blob) = self.read_fileblock(offset)?;
    if offset == 0 { // header
      Ok((len, vec![]))
    } else {
      Ok((len, blob.decode_primitive()?.decode()))
    }
  }
}