osmpbf_parser/
decode.rs

1use crate::proto;
2use crate::proto::osmformat::{HeaderBlock,PrimitiveBlock};
3use quick_protobuf::{MessageRead,Reader};
4use flate2::read::ZlibDecoder;
5use std::io::Read;
6use crate::{element,Blob};
7
8type Error = Box<dyn std::error::Error+Send+Sync+'static>;
9
10impl Blob {
11  pub fn decode_header(&self) -> Result<HeaderBlock,Error> {
12    let data = self.get_data()?;
13    let header_block = Reader::from_bytes(data)
14      .read(HeaderBlock::from_reader)?;
15    Ok(header_block)
16  }
17  pub fn decode_primitive(&self) -> Result<PrimitiveBlock,Error> {
18    let data = self.get_data()?;
19    let primitive_block = Reader::from_bytes(data)
20      .read(PrimitiveBlock::from_reader)?;
21    Ok(primitive_block)
22  }
23  pub fn get_data(&self) -> Result<Vec<u8>,Error> {
24    if let Some(data) = &self.raw {
25      Ok(data.clone())
26    } else if let Some(input) = &self.zlib_data {
27      let mut z = ZlibDecoder::new(&input[..]);
28      let mut data = vec![];
29      z.read_to_end(&mut data)?;
30      Ok(data)
31    } else {
32      panic!["unsupported compression type"];
33    }
34  }
35}
36
37impl PrimitiveBlock {
38  pub fn decode(&self) -> Vec<element::Element> {
39    let mut elements = vec![];
40    for g in self.primitivegroup.iter() {
41      for node in g.nodes.iter() {
42        elements.push(element::Element::Node(element::Node {
43          id: node.id,
44          tags: self.tags(&node.keys, &node.vals),
45          info: node.info.as_ref().map(|info| self.info(info)),
46          lon: (self.lon_offset + (self.granularity as i64 * node.lon)) as f64 * 1e-9,
47          lat: (self.lat_offset + (self.granularity as i64 * node.lat)) as f64 * 1e-9,
48        }));
49      }
50      if let Some(dense) = &g.dense {
51        let mut prev_id = 0;
52        let mut prev_lon = 0;
53        let mut prev_lat = 0;
54        let mut prev_timestamp = 0;
55        let mut prev_changeset = 0;
56        let mut prev_uid = 0;
57        let mut prev_user_sid = 0;
58        let mut tag_i = 0;
59        let mut info_i = 0;
60        let z = dense.id.iter().zip(dense.lon.iter().zip(dense.lat.iter()));
61        for (d_id,(d_lon,d_lat)) in z {
62          let id = *d_id + prev_id;
63          let lon = *d_lon + prev_lon;
64          let lat = *d_lat + prev_lat;
65
66          let mut tags = vec![];
67          while tag_i+1 < dense.keys_vals.len() && dense.keys_vals[tag_i] != 0 {
68            tags.push((
69              self.get_string(dense.keys_vals[tag_i+0] as usize),
70              self.get_string(dense.keys_vals[tag_i+1] as usize),
71            ));
72            tag_i += 2;
73          }
74          tag_i += 1;
75          let info = dense.denseinfo.as_ref().map(|info| {
76            let timestamp = info.timestamp.get(info_i).map(|x| prev_timestamp+*x);
77            let changeset = info.changeset.get(info_i).map(|x| prev_changeset+*x);
78            let uid = info.uid.get(info_i).map(|x| prev_uid+*x);
79            let user_sid = info.user_sid.get(info_i).map(|x| prev_user_sid+*x);
80            let einfo = element::Info {
81              version: info.version.get(info_i).cloned().unwrap_or(0),
82              timestamp,
83              changeset,
84              uid,
85              user: user_sid.map(|i| self.get_string(i as usize)),
86              visible: info.visible.get(info_i).cloned(),
87            };
88            info_i += 1;
89            prev_timestamp = timestamp.unwrap_or(0);
90            prev_changeset = changeset.unwrap_or(0);
91            prev_uid = uid.unwrap_or(0);
92            prev_user_sid = user_sid.unwrap_or(0);
93            einfo
94          });
95          elements.push(element::Element::Node(element::Node {
96            id: id,
97            tags,
98            info,
99            lon: (self.lon_offset + (self.granularity as i64 * lon)) as f64 * 1e-9,
100            lat: (self.lat_offset + (self.granularity as i64 * lat)) as f64 * 1e-9,
101          }));
102          prev_id = id;
103          prev_lon = lon;
104          prev_lat = lat;
105        }
106      }
107      for way in g.ways.iter() {
108        let mut refs = vec![];
109        let mut prev_ref = 0;
110        for r in way.refs.iter() {
111          //refs.push(r + prev_ref);
112          refs.push(prev_ref + *r);
113          prev_ref += r;
114        }
115        elements.push(element::Element::Way(element::Way {
116          id: way.id,
117          tags: self.tags(&way.keys, &way.vals),
118          info: way.info.as_ref().map(|info| self.info(info)),
119          refs,
120        }));
121      }
122      for relation in g.relations.iter() {
123        let mut members = vec![];
124        let mut prev_mem_id = 0;
125        let z = relation.memids.iter().zip(relation.roles_sid.iter()).zip(relation.types.iter());
126        for ((mem_id,role_sid),mem_type) in z {
127          members.push(element::Member {
128            id: mem_id + prev_mem_id,
129            role: self.get_string(*role_sid as usize),
130            member_type: match mem_type {
131              proto::osmformat::mod_Relation::MemberType::NODE => element::MemberType::Node,
132              proto::osmformat::mod_Relation::MemberType::WAY => element::MemberType::Way,
133              proto::osmformat::mod_Relation::MemberType::RELATION => element::MemberType::Relation,
134            },
135          });
136          prev_mem_id = mem_id + prev_mem_id;
137        }
138        elements.push(element::Element::Relation(element::Relation {
139          id: relation.id,
140          tags: self.tags(&relation.keys, &relation.vals),
141          info: relation.info.as_ref().map(|info| self.info(info)),
142          members,
143        }));
144      }
145    }
146    elements
147  }
148  fn tags<'a>(&self, keys: &[u32], values: &[u32]) -> element::Tags {
149    keys.iter().zip(values.iter()).map(|(ki,vi)| {
150      let key = self.get_string(*ki as usize);
151      let value = self.get_string(*vi as usize);
152      (key, value)
153    }).collect()
154  }
155  fn info(&self, info: &proto::osmformat::Info) -> element::Info {
156    element::Info {
157      version: info.version,
158      timestamp: info.timestamp,
159      changeset: info.changeset,
160      uid: info.uid,
161      user: info.user_sid.map(|i| self.get_string(i as usize)),
162      visible: info.visible,
163    }
164  }
165  pub fn get_string(&self, i: usize) -> String {
166    let s = &self.stringtable.s[i];
167    String::from_utf8(s.to_vec()).unwrap()
168  }
169}