osm_pbf_iter/
blob_reader.rs

1use 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                    // retry next
54                    Self::read_blob(read)
55                } else {
56                    match parse_blob(&blob_buf) {
57                        Some(blob) =>
58                            Some(blob),
59                        None =>
60                            // retry next
61                            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            // type
91            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                    // Immediately terminate Iterator
99                    return None
100                }
101            },
102            // datasize
103            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            // raw
116            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