1use super::*;
2use crate::{Lat, Lon, OSMObj, OSMObjectType, ObjId, TimestampFormat};
3use std::rc::Rc;
4
5macro_rules! func_call_inner_get {
6 ($slf:ident, $name:ident) => {
7 match $slf {
8 RcOSMObj::Node(x) => x.$name(),
9 RcOSMObj::Way(x) => x.$name(),
10 RcOSMObj::Relation(x) => x.$name(),
11 }
12 };
13}
14
15macro_rules! func_call_inner_set {
16 ($slf:ident, $name:ident, $val:ident) => {
17 match $slf {
18 RcOSMObj::Node(x) => x.$name($val),
19 RcOSMObj::Way(x) => x.$name($val),
20 RcOSMObj::Relation(x) => x.$name($val),
21 };
22 };
23}
24
25#[derive(Clone, PartialEq, Debug)]
26pub struct RcNode {
27 pub(crate) _id: ObjId,
28 pub(crate) _version: Option<u32>,
29 pub(crate) _deleted: bool,
30 pub(crate) _changeset_id: Option<u32>,
31 pub(crate) _timestamp: Option<TimestampFormat>,
32 pub(crate) _uid: Option<u32>,
33 pub(crate) _user: Option<Rc<str>>,
34 pub(crate) _tags: Option<Vec<(Rc<str>, Rc<str>)>>,
35
36 pub(crate) _lat_lon: Option<(Lat, Lon)>,
37}
38
39#[derive(Clone, PartialEq, Debug)]
40pub struct RcWay {
41 pub(crate) _id: ObjId,
42 pub(crate) _version: Option<u32>,
43 pub(crate) _deleted: bool,
44 pub(crate) _changeset_id: Option<u32>,
45 pub(crate) _timestamp: Option<TimestampFormat>,
46 pub(crate) _uid: Option<u32>,
47 pub(crate) _user: Option<Rc<str>>,
48 pub(crate) _tags: Vec<(Rc<str>, Rc<str>)>,
49
50 pub(crate) _nodes: Vec<ObjId>,
51}
52
53#[derive(Clone, PartialEq, Debug)]
54pub struct RcRelation {
55 pub(crate) _id: ObjId,
56 pub(crate) _version: Option<u32>,
57 pub(crate) _deleted: bool,
58 pub(crate) _changeset_id: Option<u32>,
59 pub(crate) _timestamp: Option<TimestampFormat>,
60 pub(crate) _uid: Option<u32>,
61 pub(crate) _user: Option<Rc<str>>,
62 pub(crate) _tags: Vec<(Rc<str>, Rc<str>)>,
63
64 pub(crate) _members: Vec<(OSMObjectType, ObjId, Rc<str>)>,
65}
66
67#[derive(Clone, PartialEq, Debug)]
68pub enum RcOSMObj {
69 Node(RcNode),
70 Way(RcWay),
71 Relation(RcRelation),
72}
73
74impl OSMObjBase for RcOSMObj {
75 fn id(&self) -> ObjId {
76 func_call_inner_get!(self, id)
77 }
78 fn version(&self) -> Option<u32> {
79 func_call_inner_get!(self, version)
80 }
81 fn deleted(&self) -> bool {
82 func_call_inner_get!(self, deleted)
83 }
84 fn changeset_id(&self) -> Option<u32> {
85 func_call_inner_get!(self, changeset_id)
86 }
87 fn timestamp(&self) -> &Option<TimestampFormat> {
88 func_call_inner_get!(self, timestamp)
89 }
90 fn uid(&self) -> Option<u32> {
91 func_call_inner_get!(self, uid)
92 }
93 fn user(&self) -> Option<&str> {
94 func_call_inner_get!(self, user)
95 }
96
97 fn set_id(&mut self, val: impl Into<ObjId>) {
98 func_call_inner_set!(self, set_id, val);
99 }
100 fn set_version(&mut self, val: impl Into<Option<u32>>) {
101 func_call_inner_set!(self, set_version, val);
102 }
103 fn set_deleted(&mut self, val: bool) {
104 func_call_inner_set!(self, set_deleted, val);
105 }
106 fn set_changeset_id(&mut self, val: impl Into<Option<u32>>) {
107 func_call_inner_set!(self, set_changeset_id, val);
108 }
109 fn set_timestamp(&mut self, val: impl Into<Option<TimestampFormat>>) {
110 func_call_inner_set!(self, set_timestamp, val);
111 }
112 fn set_uid(&mut self, val: impl Into<Option<u32>>) {
113 func_call_inner_set!(self, set_uid, val);
114 }
115 fn set_user<'a>(&mut self, val: impl Into<Option<&'a str>>) {
116 func_call_inner_set!(self, set_user, val);
117 }
118
119 fn tags<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = (&'a str, &'a str)> + 'a> {
120 match self {
121 RcOSMObj::Node(x) => x.tags(),
122 RcOSMObj::Way(x) => x.tags(),
123 RcOSMObj::Relation(x) => x.tags(),
124 }
125 }
126
127 fn num_tags(&self) -> usize {
128 match self {
129 RcOSMObj::Node(x) => x._tags.as_ref().map_or(0, |t| t.len()),
130 RcOSMObj::Way(x) => x._tags.len(),
131 RcOSMObj::Relation(x) => x._tags.len(),
132 }
133 }
134 fn untagged(&self) -> bool {
135 match self {
136 RcOSMObj::Node(x) => x._tags.as_ref().map_or(true, |t| t.is_empty()),
137 RcOSMObj::Way(x) => x._tags.is_empty(),
138 RcOSMObj::Relation(x) => x._tags.is_empty(),
139 }
140 }
141
142 fn tag(&self, key: impl AsRef<str>) -> Option<&str> {
143 match self {
144 RcOSMObj::Node(x) => x.tag(key),
145 RcOSMObj::Way(x) => x.tag(key),
146 RcOSMObj::Relation(x) => x.tag(key),
147 }
148 }
149
150 fn set_tag(&mut self, key: impl AsRef<str>, value: impl Into<String>) {
151 match self {
152 RcOSMObj::Node(x) => x.set_tag(key, value),
153 RcOSMObj::Way(x) => x.set_tag(key, value),
154 RcOSMObj::Relation(x) => x.set_tag(key, value),
155 }
156 }
157
158 fn unset_tag(&mut self, key: impl AsRef<str>) {
159 match self {
160 RcOSMObj::Node(x) => x.unset_tag(key),
161 RcOSMObj::Way(x) => x.unset_tag(key),
162 RcOSMObj::Relation(x) => x.unset_tag(key),
163 }
164 }
165
166 fn object_type(&self) -> OSMObjectType {
167 match self {
168 RcOSMObj::Node(_) => OSMObjectType::Node,
169 RcOSMObj::Way(_) => OSMObjectType::Way,
170 RcOSMObj::Relation(_) => OSMObjectType::Relation,
171 }
172 }
173}
174
175impl OSMObj for RcOSMObj {
176 type Node = RcNode;
177 type Way = RcWay;
178 type Relation = RcRelation;
179
180 fn into_node(self) -> Option<RcNode> {
181 if let RcOSMObj::Node(n) = self {
182 Some(n)
183 } else {
184 None
185 }
186 }
187
188 fn into_way(self) -> Option<RcWay> {
189 if let RcOSMObj::Way(w) = self {
190 Some(w)
191 } else {
192 None
193 }
194 }
195
196 fn into_relation(self) -> Option<RcRelation> {
197 if let RcOSMObj::Relation(r) = self {
198 Some(r)
199 } else {
200 None
201 }
202 }
203
204 fn as_node(&self) -> Option<&RcNode> {
205 if let RcOSMObj::Node(n) = self {
206 Some(n)
207 } else {
208 None
209 }
210 }
211
212 fn as_way(&self) -> Option<&RcWay> {
213 if let RcOSMObj::Way(w) = self {
214 Some(w)
215 } else {
216 None
217 }
218 }
219
220 fn as_relation(&self) -> Option<&RcRelation> {
221 if let RcOSMObj::Relation(r) = self {
222 Some(r)
223 } else {
224 None
225 }
226 }
227
228 fn as_node_mut(&mut self) -> Option<&mut RcNode> {
229 if let RcOSMObj::Node(n) = self {
230 Some(n)
231 } else {
232 None
233 }
234 }
235
236 fn as_way_mut(&mut self) -> Option<&mut RcWay> {
237 if let RcOSMObj::Way(w) = self {
238 Some(w)
239 } else {
240 None
241 }
242 }
243
244 fn as_relation_mut(&mut self) -> Option<&mut RcRelation> {
245 if let RcOSMObj::Relation(r) = self {
246 Some(r)
247 } else {
248 None
249 }
250 }
251}
252
253impl OSMObjBase for RcNode {
254 fn id(&self) -> ObjId {
255 self._id
256 }
257 fn version(&self) -> Option<u32> {
258 self._version
259 }
260 fn deleted(&self) -> bool {
261 self._deleted
262 }
263 fn changeset_id(&self) -> Option<u32> {
264 self._changeset_id
265 }
266 fn timestamp(&self) -> &Option<TimestampFormat> {
267 &self._timestamp
268 }
269 fn uid(&self) -> Option<u32> {
270 self._uid
271 }
272 fn user(&self) -> Option<&str> {
273 self._user.as_ref().map(|x| x as _)
274 }
275
276 fn set_id(&mut self, val: impl Into<ObjId>) {
277 self._id = val.into();
278 }
279 fn set_version(&mut self, val: impl Into<Option<u32>>) {
280 self._version = val.into();
281 }
282 fn set_deleted(&mut self, val: bool) {
283 self._deleted = val;
284 }
285 fn set_changeset_id(&mut self, val: impl Into<Option<u32>>) {
286 self._changeset_id = val.into();
287 }
288 fn set_timestamp(&mut self, val: impl Into<Option<TimestampFormat>>) {
289 self._timestamp = val.into();
290 }
291 fn set_uid(&mut self, val: impl Into<Option<u32>>) {
292 self._uid = val.into();
293 }
294 fn set_user<'a>(&mut self, val: impl Into<Option<&'a str>>) {
295 self._user = val.into().map(Rc::from);
296 }
297
298 fn tags<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = (&'a str, &'a str)> + 'a> {
299 match self._tags {
300 None => Box::new(std::iter::empty()),
301 Some(ref t) => Box::new(t.iter().map(|(k, v)| (k.as_ref(), v.as_ref()))),
302 }
303 }
304
305 fn tag(&self, key: impl AsRef<str>) -> Option<&str> {
306 match &self._tags {
307 None => None,
308 Some(t) => {
309 let key = key.as_ref();
310 t.iter()
311 .filter_map(|(k, v)| {
312 if k.as_ref() == key {
313 Some(v.as_ref())
314 } else {
315 None
316 }
317 })
318 .next()
319 }
320 }
321 }
322
323 fn set_tag(&mut self, key: impl AsRef<str>, value: impl Into<String>) {
324 let key = key.as_ref();
325 let value = value.into();
326 match self._tags {
327 None => {
328 self._tags = Some(vec![(Rc::from(key), Rc::from(value.as_str()))]);
329 }
330 Some(ref mut tags) => {
331 let idx = tags
332 .iter()
333 .enumerate()
334 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
335 .next();
336 match idx {
337 None => tags.push((Rc::from(key), Rc::from(value.as_str()))),
338 Some(i) => tags[i] = (key.into(), Rc::from(value.as_str())),
339 }
340 }
341 }
342 }
343
344 fn unset_tag(&mut self, key: impl AsRef<str>) {
345 if let Some(ref mut tags) = self._tags {
346 let key = key.as_ref();
347 let idx = tags
348 .iter()
349 .enumerate()
350 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
351 .next();
352 if let Some(i) = idx {
353 tags.remove(i);
354 }
355 }
356 }
357
358 fn object_type(&self) -> OSMObjectType {
359 OSMObjectType::Node
360 }
361}
362
363impl Node for RcNode {
364 fn lat_lon(&self) -> Option<(Lat, Lon)> {
365 self._lat_lon
366 }
367
368 fn set_lat_lon_direct(&mut self, loc: Option<(Lat, Lon)>) {
369 self._lat_lon = loc;
370 }
371}
372
373impl OSMObjBase for RcWay {
374 fn id(&self) -> ObjId {
375 self._id
376 }
377 fn version(&self) -> Option<u32> {
378 self._version
379 }
380 fn deleted(&self) -> bool {
381 self._deleted
382 }
383 fn changeset_id(&self) -> Option<u32> {
384 self._changeset_id
385 }
386 fn timestamp(&self) -> &Option<TimestampFormat> {
387 &self._timestamp
388 }
389 fn uid(&self) -> Option<u32> {
390 self._uid
391 }
392 fn user(&self) -> Option<&str> {
393 self._user.as_ref().map(|x| x as _)
394 }
395
396 fn set_id(&mut self, val: impl Into<ObjId>) {
397 self._id = val.into();
398 }
399 fn set_version(&mut self, val: impl Into<Option<u32>>) {
400 self._version = val.into();
401 }
402 fn set_deleted(&mut self, val: bool) {
403 self._deleted = val;
404 }
405 fn set_changeset_id(&mut self, val: impl Into<Option<u32>>) {
406 self._changeset_id = val.into();
407 }
408 fn set_timestamp(&mut self, val: impl Into<Option<TimestampFormat>>) {
409 self._timestamp = val.into();
410 }
411 fn set_uid(&mut self, val: impl Into<Option<u32>>) {
412 self._uid = val.into();
413 }
414 fn set_user<'a>(&mut self, val: impl Into<Option<&'a str>>) {
415 self._user = val.into().map(Rc::from);
416 }
417
418 fn tags<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = (&'a str, &'a str)> + 'a> {
419 Box::new(self._tags.iter().map(|(k, v)| (k.as_ref(), v.as_ref())))
420 }
421
422 fn tag(&self, key: impl AsRef<str>) -> Option<&str> {
423 let key = key.as_ref();
424 self._tags
425 .iter()
426 .filter_map(|(k, v)| {
427 if k.as_ref() == key {
428 Some(v.as_ref())
429 } else {
430 None
431 }
432 })
433 .next()
434 }
435
436 fn set_tag(&mut self, key: impl AsRef<str>, value: impl Into<String>) {
437 let key = key.as_ref();
438 let value = value.into();
439 let idx = self
440 ._tags
441 .iter()
442 .enumerate()
443 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
444 .next();
445 match idx {
446 None => self._tags.push((Rc::from(key), Rc::from(value.as_str()))),
447 Some(i) => self._tags[i] = (key.into(), Rc::from(value.as_str())),
448 }
449 }
450
451 fn unset_tag(&mut self, key: impl AsRef<str>) {
452 let key = key.as_ref();
453 let idx = self
454 ._tags
455 .iter()
456 .enumerate()
457 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
458 .next();
459 if let Some(i) = idx {
460 self._tags.remove(i);
461 }
462 }
463
464 fn object_type(&self) -> OSMObjectType {
465 OSMObjectType::Way
466 }
467}
468
469impl Way for RcWay {
470 fn nodes(&self) -> &[ObjId] {
471 &self._nodes
472 }
473
474 fn num_nodes(&self) -> usize {
475 self._nodes.len()
476 }
477
478 fn node(&self, idx: usize) -> Option<ObjId> {
479 self._nodes.get(idx).cloned()
480 }
481 fn set_nodes(&mut self, nodes: impl IntoIterator<Item = impl Into<ObjId>>) {
482 self._nodes.truncate(0);
483 self._nodes.extend(nodes.into_iter().map(|i| i.into()));
484 }
485}
486
487impl OSMObjBase for RcRelation {
488 fn id(&self) -> ObjId {
489 self._id
490 }
491 fn version(&self) -> Option<u32> {
492 self._version
493 }
494 fn deleted(&self) -> bool {
495 self._deleted
496 }
497 fn changeset_id(&self) -> Option<u32> {
498 self._changeset_id
499 }
500 fn timestamp(&self) -> &Option<TimestampFormat> {
501 &self._timestamp
502 }
503 fn uid(&self) -> Option<u32> {
504 self._uid
505 }
506 fn user(&self) -> Option<&str> {
507 self._user.as_ref().map(|x| x as _)
508 }
509
510 fn set_id(&mut self, val: impl Into<ObjId>) {
511 self._id = val.into();
512 }
513 fn set_version(&mut self, val: impl Into<Option<u32>>) {
514 self._version = val.into();
515 }
516 fn set_deleted(&mut self, val: bool) {
517 self._deleted = val;
518 }
519 fn set_changeset_id(&mut self, val: impl Into<Option<u32>>) {
520 self._changeset_id = val.into();
521 }
522 fn set_timestamp(&mut self, val: impl Into<Option<TimestampFormat>>) {
523 self._timestamp = val.into();
524 }
525 fn set_uid(&mut self, val: impl Into<Option<u32>>) {
526 self._uid = val.into();
527 }
528 fn set_user<'a>(&mut self, val: impl Into<Option<&'a str>>) {
529 self._user = val.into().map(Rc::from);
530 }
531
532 fn tags<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = (&'a str, &'a str)> + 'a> {
533 Box::new(self._tags.iter().map(|(k, v)| (k.as_ref(), v.as_ref())))
534 }
535
536 fn tag(&self, key: impl AsRef<str>) -> Option<&str> {
537 let key = key.as_ref();
538 self._tags
539 .iter()
540 .filter_map(|(k, v)| {
541 if k.as_ref() == key {
542 Some(v.as_ref())
543 } else {
544 None
545 }
546 })
547 .next()
548 }
549
550 fn set_tag(&mut self, key: impl AsRef<str>, value: impl Into<String>) {
551 let key = key.as_ref();
552 let value = value.into();
553 let idx = self
554 ._tags
555 .iter()
556 .enumerate()
557 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
558 .next();
559 match idx {
560 None => self._tags.push((Rc::from(key), Rc::from(value.as_str()))),
561 Some(i) => self._tags[i] = (key.into(), Rc::from(value.as_str())),
562 }
563 }
564
565 fn unset_tag(&mut self, key: impl AsRef<str>) {
566 let key = key.as_ref();
567 let idx = self
568 ._tags
569 .iter()
570 .enumerate()
571 .filter_map(|(i, (k, _))| if k.as_ref() == key { Some(i) } else { None })
572 .next();
573 if let Some(i) = idx {
574 self._tags.remove(i);
575 }
576 }
577
578 fn object_type(&self) -> OSMObjectType {
579 OSMObjectType::Relation
580 }
581}
582
583impl Relation for RcRelation {
584 fn members<'a>(
585 &'a self,
586 ) -> Box<dyn ExactSizeIterator<Item = (OSMObjectType, ObjId, &'a str)> + 'a> {
587 Box::new(self._members.iter().map(|(t, o, r)| (*t, *o, r.as_ref())))
588 }
589
590 fn set_members(
591 &mut self,
592 members: impl IntoIterator<Item = (OSMObjectType, ObjId, impl Into<String>)>,
593 ) {
594 self._members.truncate(0);
595
596 self._members.extend(
597 members
598 .into_iter()
599 .map(|(t, i, r)| (t, i, Rc::from(r.into()))),
600 );
601 }
602}