osm_pbf_iter/
blob_reader.rs1use std::str::from_utf8;
2use std::io::Read;
3use byteorder::{ByteOrder, BigEndian};
4
5use protobuf_iter::*;
6use blob::Blob;
7
8
9pub struct BlobReader<R> {
10 read: R
11}
12
13impl<R: Read> BlobReader<R> {
14 pub fn new(r: R) -> Self {
15 BlobReader {
16 read: r
17 }
18 }
19
20 pub fn into_inner(self) -> R {
21 self.read
22 }
23
24 pub fn get_mut(&mut self) -> &mut R {
25 &mut self.read
26 }
27
28 pub fn read_blob(read: &mut R) -> Option<Blob> {
29 let mut len_buf = [0; 4];
30 match read.read(&mut len_buf) {
31 Ok(4) => {
32 let len = BigEndian::read_u32(&len_buf) as usize;
33 let mut header_buf = Vec::with_capacity(len);
34 unsafe { header_buf.set_len(len); }
35 match read.read_exact(&mut header_buf) {
36 Ok(()) => (),
37 _ => return None
38 };
39
40 let blob_header = match parse_blob_header(&header_buf) {
41 Some(blob_header) => blob_header,
42 None => return None
43 };
44 let datasize = blob_header.datasize as usize;
45 let mut blob_buf = Vec::with_capacity(datasize);
46 unsafe { blob_buf.set_len(datasize); }
47 match read.read_exact(&mut blob_buf) {
48 Ok(()) => (),
49 _ => return None
50 };
51
52 if ! blob_header.is_osm_data {
53 Self::read_blob(read)
55 } else {
56 match parse_blob(&blob_buf) {
57 Some(blob) =>
58 Some(blob),
59 None =>
60 Self::read_blob(read)
62 }
63 }
64 },
65 _ => None
66 }
67 }
68}
69
70impl<R: Read> Iterator for BlobReader<R> {
71 type Item = Blob;
72
73 fn next(&mut self) -> Option<Self::Item> {
74 Self::read_blob(&mut self.read)
75 }
76}
77
78struct BlobHeader {
79 is_osm_data: bool,
80 datasize: u32
81}
82
83fn parse_blob_header(data: &[u8]) -> Option<BlobHeader> {
84 let mut blob_header = BlobHeader {
85 is_osm_data: false,
86 datasize: 0
87 };
88 for m in MessageIter::new(&data) {
89 match m.tag {
90 1 => {
92 let value = m.value.get_data();
93 if value == b"OSMData" {
94 blob_header.is_osm_data = true;
95 } else if value != b"OSMHeader" {
96 println!("Encountered something other than OSM data: {}!",
97 from_utf8(value).unwrap());
98 return None
100 }
101 },
102 3 => {
104 blob_header.datasize = From::from(m.value);
105 },
106 _ => ()
107 }
108 }
109 Some(blob_header)
110}
111
112fn parse_blob(data: &[u8]) -> Option<Blob> {
113 for m in MessageIter::new(&data) {
114 match m.tag {
115 1 => {
117 return Some(Blob::Raw(Vec::from(m.value.get_data())))
118 },
119 3 => {
120 return Some(Blob::Zlib(Vec::from(m.value.get_data())))
121 },
122 _ => ()
123 }
124 }
125
126 None
127}
128