butterfly_dl/core/
source.rs

1//! Source resolution logic for butterfly-dl
2//!
3//! Handles HTTP source routing for OpenStreetMap data downloads.
4
5use butterfly_common::Result;
6
7/// Represents different download sources
8#[derive(Debug, Clone, PartialEq)]
9pub enum DownloadSource {
10    /// HTTP source with direct URL
11    Http { url: String },
12}
13
14/// Configuration for download sources
15pub struct SourceConfig {
16    /// HTTP URL for planet files
17    pub planet_http_url: String,
18
19    /// Base URL for Geofabrik downloads
20    pub geofabrik_base_url: String,
21}
22
23impl Default for SourceConfig {
24    fn default() -> Self {
25        Self {
26            planet_http_url: "https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf"
27                .to_string(),
28            geofabrik_base_url: "https://download.geofabrik.de".to_string(),
29        }
30    }
31}
32
33/// Resolves a source string to a download source
34pub fn resolve_source(source: &str, config: &SourceConfig) -> Result<DownloadSource> {
35    match source {
36        "planet" => resolve_planet_source(config),
37        path if path.contains('/') => Ok(DownloadSource::Http {
38            url: format!("{}/{}-latest.osm.pbf", config.geofabrik_base_url, path),
39        }),
40        continent => Ok(DownloadSource::Http {
41            url: format!("{}/{}-latest.osm.pbf", config.geofabrik_base_url, continent),
42        }),
43    }
44}
45
46/// Resolves planet source to HTTP download
47fn resolve_planet_source(config: &SourceConfig) -> Result<DownloadSource> {
48    Ok(DownloadSource::Http {
49        url: config.planet_http_url.clone(),
50    })
51}
52
53/// Generates output filename from source
54pub fn resolve_output_filename(source: &str) -> String {
55    match source {
56        "planet" => "planet-latest.osm.pbf".to_string(),
57        path if path.contains('/') => {
58            let name = path.split('/').next_back().unwrap_or(path);
59            format!("{name}-latest.osm.pbf")
60        }
61        continent => format!("{continent}-latest.osm.pbf"),
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_resolve_planet_source() {
71        let config = SourceConfig::default();
72        let source = resolve_source("planet", &config).unwrap();
73
74        match source {
75            DownloadSource::Http { url } => {
76                assert_eq!(
77                    url,
78                    "https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf"
79                );
80            }
81        }
82    }
83
84    #[test]
85    fn test_resolve_continent_source() {
86        let config = SourceConfig::default();
87        let source = resolve_source("europe", &config).unwrap();
88
89        match source {
90            DownloadSource::Http { url } => {
91                assert_eq!(url, "https://download.geofabrik.de/europe-latest.osm.pbf");
92            }
93        }
94    }
95
96    #[test]
97    fn test_resolve_country_source() {
98        let config = SourceConfig::default();
99        let source = resolve_source("europe/belgium", &config).unwrap();
100
101        match source {
102            DownloadSource::Http { url } => {
103                assert_eq!(
104                    url,
105                    "https://download.geofabrik.de/europe/belgium-latest.osm.pbf"
106                );
107            }
108        }
109    }
110
111    #[test]
112    fn test_resolve_output_filename() {
113        assert_eq!(resolve_output_filename("planet"), "planet-latest.osm.pbf");
114        assert_eq!(resolve_output_filename("europe"), "europe-latest.osm.pbf");
115        assert_eq!(
116            resolve_output_filename("europe/belgium"),
117            "belgium-latest.osm.pbf"
118        );
119    }
120}