Преглед на файлове

Fix DenseNodeIter when dense node info is empty

Nikolay Mikov преди 5 години
родител
ревизия
ee82ea359b
променени са 2 файла, в които са добавени 124 реда и са изтрити 73 реда
  1. 121
    70
      src/dense.rs
  2. 3
    3
      tests/read.rs

+ 121
- 70
src/dense.rs Целия файл

@@ -14,23 +14,16 @@ pub struct DenseNode<'a> {
14 14
     /// The node id. It should be unique between nodes and might be negative to indicate
15 15
     /// that the element has not yet been uploaded to a server.
16 16
     pub id: i64,
17
-    /// The version of this element.
18
-    pub version: i32,
19
-    timestamp: i64,
20
-    /// The changeset id.
21
-    pub changeset: i64,
22
-    /// The user id.
23
-    pub uid: i32,
24
-    user_sid: i32,
25 17
     lat: i64,
26 18
     lon: i64,
27 19
     keys_vals_indices: &'a [i32],
20
+    info: Option<DenseNodeInfo<'a>>,
28 21
 }
29 22
 
30 23
 impl<'a> DenseNode<'a> {
31
-    /// Returns the user name.
32
-    pub fn user(&self) -> Result<&'a str> {
33
-        str_from_stringtable(self.block, self.user_sid as usize)
24
+    /// return optional metadata about the ndode
25
+    pub fn info(&'a self) -> Option<&'a DenseNodeInfo<'a>> {
26
+        self.info.as_ref()
34 27
     }
35 28
 
36 29
     /// Returns the latitude coordinate in degrees.
@@ -63,11 +56,6 @@ impl<'a> DenseNode<'a> {
63 56
         (self.nano_lon() / 100) as i32
64 57
     }
65 58
 
66
-    /// Returns the time stamp in milliseconds since the epoch.
67
-    pub fn milli_timestamp(&self) -> i64 {
68
-        self.timestamp * i64::from(self.block.get_date_granularity())
69
-    }
70
-
71 59
     /// Returns an iterator over the tags of this node (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
72 60
     pub fn tags(&self) -> DenseTagIter<'a> {
73 61
         DenseTagIter {
@@ -91,23 +79,15 @@ impl<'a> DenseNode<'a> {
91 79
 #[derive(Clone, Debug)]
92 80
 pub struct DenseNodeIter<'a> {
93 81
     block: &'a osmformat::PrimitiveBlock,
94
-    dids: std::slice::Iter<'a, i64>, // deltas
95
-    cid: i64,                        // current id
96
-    versions: std::slice::Iter<'a, i32>,
97
-    dtimestamps: std::slice::Iter<'a, i64>, // deltas
98
-    ctimestamp: i64,
99
-    dchangesets: std::slice::Iter<'a, i64>, // deltas
100
-    cchangeset: i64,
101
-    duids: std::slice::Iter<'a, i32>, // deltas
102
-    cuid: i32,
103
-    duser_sids: std::slice::Iter<'a, i32>, // deltas
104
-    cuser_sid: i32,
82
+    dids: std::slice::Iter<'a, i64>,  // deltas
83
+    cid: i64,                         // current id
105 84
     dlats: std::slice::Iter<'a, i64>, // deltas
106 85
     clat: i64,
107 86
     dlons: std::slice::Iter<'a, i64>, // deltas
108 87
     clon: i64,
109 88
     keys_vals_slice: &'a [i32],
110 89
     keys_vals_index: usize,
90
+    info_iter: Option<DenseNodeInfoIter<'a>>,
111 91
 }
112 92
 
113 93
 impl<'a> DenseNodeIter<'a> {
@@ -115,26 +95,18 @@ impl<'a> DenseNodeIter<'a> {
115 95
         block: &'a osmformat::PrimitiveBlock,
116 96
         osmdense: &'a osmformat::DenseNodes,
117 97
     ) -> DenseNodeIter<'a> {
118
-        let info = osmdense.get_denseinfo();
98
+        let info_iter = Some(DenseNodeInfoIter::new(block, osmdense.get_denseinfo()));
119 99
         DenseNodeIter {
120 100
             block,
121 101
             dids: osmdense.get_id().iter(),
122 102
             cid: 0,
123
-            versions: info.get_version().iter(),
124
-            dtimestamps: info.get_timestamp().iter(),
125
-            ctimestamp: 0,
126
-            dchangesets: info.get_changeset().iter(),
127
-            cchangeset: 0,
128
-            duids: info.get_uid().iter(),
129
-            cuid: 0,
130
-            duser_sids: info.get_user_sid().iter(),
131
-            cuser_sid: 0,
132 103
             dlats: osmdense.get_lat().iter(),
133 104
             clat: 0,
134 105
             dlons: osmdense.get_lon().iter(),
135 106
             clon: 0,
136 107
             keys_vals_slice: osmdense.get_keys_vals(),
137 108
             keys_vals_index: 0,
109
+            info_iter,
138 110
         }
139 111
     }
140 112
 
@@ -143,21 +115,13 @@ impl<'a> DenseNodeIter<'a> {
143 115
             block,
144 116
             dids: [].iter(),
145 117
             cid: 0,
146
-            versions: [].iter(),
147
-            dtimestamps: [].iter(),
148
-            ctimestamp: 0,
149
-            dchangesets: [].iter(),
150
-            cchangeset: 0,
151
-            duids: [].iter(),
152
-            cuid: 0,
153
-            duser_sids: [].iter(),
154
-            cuser_sid: 0,
155 118
             dlats: [].iter(),
156 119
             clat: 0,
157 120
             dlons: [].iter(),
158 121
             clon: 0,
159 122
             keys_vals_slice: &[],
160 123
             keys_vals_index: 0,
124
+            info_iter: None,
161 125
         }
162 126
     }
163 127
 }
@@ -168,29 +132,12 @@ impl<'a> Iterator for DenseNodeIter<'a> {
168 132
     fn next(&mut self) -> Option<Self::Item> {
169 133
         match (
170 134
             self.dids.next(),
171
-            self.versions.next(),
172
-            self.dtimestamps.next(),
173
-            self.dchangesets.next(),
174
-            self.duids.next(),
175
-            self.duser_sids.next(),
176 135
             self.dlats.next(),
177 136
             self.dlons.next(),
137
+            self.info_iter.as_mut().and_then(|iter| iter.next()),
178 138
         ) {
179
-            (
180
-                Some(did),
181
-                Some(version),
182
-                Some(dtimestamp),
183
-                Some(dchangeset),
184
-                Some(duid),
185
-                Some(duser_sid),
186
-                Some(dlat),
187
-                Some(dlon),
188
-            ) => {
139
+            (Some(did), Some(dlat), Some(dlon), info) => {
189 140
                 self.cid += *did;
190
-                self.ctimestamp += *dtimestamp;
191
-                self.cchangeset += *dchangeset;
192
-                self.cuid += *duid;
193
-                self.cuser_sid += *duser_sid;
194 141
                 self.clat += *dlat;
195 142
                 self.clon += *dlon;
196 143
 
@@ -209,14 +156,10 @@ impl<'a> Iterator for DenseNodeIter<'a> {
209 156
                 Some(DenseNode {
210 157
                     block: self.block,
211 158
                     id: self.cid,
212
-                    version: *version,
213
-                    timestamp: self.ctimestamp,
214
-                    changeset: self.cchangeset,
215
-                    uid: self.cuid,
216
-                    user_sid: self.cuser_sid,
217 159
                     lat: self.clat,
218 160
                     lon: self.clon,
219 161
                     keys_vals_indices: &self.keys_vals_slice[start_index..end_index],
162
+                    info,
220 163
                 })
221 164
             }
222 165
             _ => None,
@@ -230,6 +173,114 @@ impl<'a> Iterator for DenseNodeIter<'a> {
230 173
 
231 174
 impl<'a> ExactSizeIterator for DenseNodeIter<'a> {}
232 175
 
176
+/// Optional metadata with non-geographic information about dense node
177
+#[derive(Clone, Debug)]
178
+pub struct DenseNodeInfo<'a> {
179
+    block: &'a osmformat::PrimitiveBlock,
180
+    /// The version of this element.
181
+    version: i32,
182
+    /// Timestamp
183
+    timestamp: i64,
184
+    /// The changeset id.
185
+    changeset: i64,
186
+    /// The user id.
187
+    uid: i32,
188
+    // String IDs for usernames.
189
+    user_sid: i32,
190
+}
191
+
192
+impl<'a> DenseNodeInfo<'a> {
193
+    /// Returns the version of this element.
194
+    pub fn version(&self) -> i32 {
195
+        self.version
196
+    }
197
+
198
+    /// Returns the changeset id.
199
+    pub fn changeset(&self) -> i64 {
200
+        self.changeset
201
+    }
202
+
203
+    /// Returns the user id.
204
+    pub fn uid(&self) -> i32 {
205
+        self.uid
206
+    }
207
+
208
+    /// Returns the user name.
209
+    pub fn user(&self) -> Result<&'a str> {
210
+        str_from_stringtable(self.block, self.user_sid as usize)
211
+    }
212
+
213
+    /// Returns the time stamp in milliseconds since the epoch.
214
+    pub fn milli_timestamp(&self) -> i64 {
215
+        self.timestamp * i64::from(self.block.get_date_granularity())
216
+    }
217
+}
218
+
219
+/// An iterator over dense nodes info. It decodes the delta encoded values.
220
+#[derive(Clone, Debug)]
221
+pub struct DenseNodeInfoIter<'a> {
222
+    block: &'a osmformat::PrimitiveBlock,
223
+    versions: std::slice::Iter<'a, i32>,
224
+    dtimestamps: std::slice::Iter<'a, i64>, // deltas
225
+    ctimestamp: i64,
226
+    dchangesets: std::slice::Iter<'a, i64>, // deltas
227
+    cchangeset: i64,
228
+    duids: std::slice::Iter<'a, i32>, // deltas
229
+    cuid: i32,
230
+    duser_sids: std::slice::Iter<'a, i32>, // deltas
231
+    cuser_sid: i32,
232
+}
233
+
234
+impl<'a> DenseNodeInfoIter<'a> {
235
+    fn new(
236
+        block: &'a osmformat::PrimitiveBlock,
237
+        info: &'a osmformat::DenseInfo,
238
+    ) -> DenseNodeInfoIter<'a> {
239
+        DenseNodeInfoIter {
240
+            block,
241
+            versions: info.get_version().iter(),
242
+            dtimestamps: info.get_timestamp().iter(),
243
+            ctimestamp: 0,
244
+            dchangesets: info.get_changeset().iter(),
245
+            cchangeset: 0,
246
+            duids: info.get_uid().iter(),
247
+            cuid: 0,
248
+            duser_sids: info.get_user_sid().iter(),
249
+            cuser_sid: 0,
250
+        }
251
+    }
252
+}
253
+
254
+impl<'a> Iterator for DenseNodeInfoIter<'a> {
255
+    type Item = DenseNodeInfo<'a>;
256
+
257
+    fn next(&mut self) -> Option<Self::Item> {
258
+        match (
259
+            self.versions.next(),
260
+            self.dtimestamps.next(),
261
+            self.dchangesets.next(),
262
+            self.duids.next(),
263
+            self.duser_sids.next(),
264
+        ) {
265
+            (Some(&version), Some(dtimestamp), Some(dchangeset), Some(duid), Some(duser_sid)) => {
266
+                self.ctimestamp += *dtimestamp;
267
+                self.cchangeset += *dchangeset;
268
+                self.cuid += *duid;
269
+                self.cuser_sid += *duser_sid;
270
+                Some(DenseNodeInfo {
271
+                    block: self.block,
272
+                    version,
273
+                    timestamp: self.ctimestamp,
274
+                    changeset: self.cchangeset,
275
+                    uid: self.cuid,
276
+                    user_sid: self.cuser_sid,
277
+                })
278
+            }
279
+            _ => None,
280
+        }
281
+    }
282
+}
283
+
233 284
 /// An iterator over the tags in a dense node.
234 285
 #[derive(Clone, Debug)]
235 286
 pub struct DenseTagIter<'a> {

+ 3
- 3
tests/read.rs Целия файл

@@ -81,9 +81,9 @@ fn check_primitive_block_content(block: &PrimitiveBlock) {
81 81
         assert_eq!(dense_nodes[1].id, 106);
82 82
         assert_eq!(dense_nodes[2].id, 108);
83 83
 
84
-        assert_eq!(dense_nodes[0].uid, 17);
85
-        assert_eq!(dense_nodes[1].uid, 17);
86
-        assert_eq!(dense_nodes[2].uid, 17);
84
+        assert_eq!(dense_nodes[0].info().map(|x| x.uid()), Some(17));
85
+        assert_eq!(dense_nodes[1].info().map(|x| x.uid()), Some(17));
86
+        assert_eq!(dense_nodes[2].info().map(|x| x.uid()), Some(17));
87 87
     }
88 88
 
89 89
     {