use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Coordinate {
pub lat: f64,
pub lon: f64,
}
impl Coordinate {
#[allow(dead_code)]
#[must_use]
pub fn new(lat: f64, lon: f64) -> Self {
Self { lat, lon }
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Way {
pub id: String,
pub node_ids: Vec<String>,
pub geometry: WayGeometry,
pub tags: HashMap<String, String>,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WayGeometry {
pub coordinates: Vec<Coordinate>,
}
impl WayGeometry {
#[allow(dead_code)]
#[must_use]
pub fn new(coordinates: Vec<Coordinate>) -> Self {
Self { coordinates }
}
#[allow(dead_code)]
#[must_use]
pub fn empty() -> Self {
Self { coordinates: Vec::new() }
}
}
impl Way {
#[allow(dead_code)]
#[must_use]
pub fn new(id: impl Into<String>, node_ids: Vec<String>, geometry: WayGeometry) -> Self {
Self {
id: id.into(),
node_ids,
geometry,
tags: HashMap::new(),
}
}
#[allow(dead_code)]
#[must_use]
pub fn with_tag(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.tags.insert(key.into(), value.into());
self
}
#[must_use]
pub fn is_oneway(&self) -> bool {
self.tags
.get("oneway")
.is_some_and(|v| v == "yes" || v == "true" || v == "1")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_coordinate_creation() {
let coord = Coordinate::new(45.5, -73.6);
assert_eq!(coord.lat, 45.5);
assert_eq!(coord.lon, -73.6);
}
#[test]
fn test_way_creation() {
let way = Way::new(
"way1",
vec!["n1".to_string(), "n2".to_string()],
WayGeometry::new(vec![Coordinate::new(45.5, -73.6), Coordinate::new(45.6, -73.7)]),
);
assert_eq!(way.id, "way1");
assert_eq!(way.node_ids.len(), 2);
assert!(!way.is_oneway());
}
#[test]
fn test_way_oneway() {
let way = Way::new("w1", vec![], WayGeometry::empty())
.with_tag("oneway", "yes");
assert!(way.is_oneway());
}
}