everymap_core/domains/
tiling.rs1use crate::error::EveryMapResult;
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7pub struct TileOptions {
8 pub format: Option<String>,
10 #[serde(default, skip_serializing_if = "Option::is_none")]
12 pub provider_extra: Option<serde_json::Value>,
13}
14
15#[derive(Debug, Clone)]
17pub struct TileResponse {
18 pub data: Vec<u8>,
19 pub content_type: Option<String>,
20}
21
22impl TileResponse {
23 pub fn new(data: Vec<u8>, content_type: Option<String>) -> Self {
25 Self { data, content_type }
26 }
27}
28
29#[async_trait]
30pub trait TileProvider: Send + Sync {
31 async fn get_tile(
32 &self,
33 z: u32,
34 x: u32,
35 y: u32,
36 options: &TileOptions,
37 ) -> EveryMapResult<TileResponse>;
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn test_tile_options_default() {
46 let options = TileOptions::default();
47 assert!(options.format.is_none());
48 assert!(options.provider_extra.is_none());
49 }
50
51 #[test]
52 fn test_tile_options_with_fields() {
53 let options = TileOptions {
54 format: Some("protobuf".to_string()),
55 provider_extra: Some(serde_json::json!({"layer": "base"})),
56 };
57 assert_eq!(options.format, Some("protobuf".to_string()));
58 }
59
60 #[test]
61 fn test_tile_response_construction() {
62 let response = TileResponse::new(vec![1, 2, 3], Some("application/x-protobuf".to_string()));
63 assert_eq!(response.data.len(), 3);
64 assert_eq!(
65 response.content_type,
66 Some("application/x-protobuf".to_string())
67 );
68 }
69
70 #[test]
73 fn test_tile_options_serde_roundtrip() {
74 let options = TileOptions {
75 format: Some("json".to_string()),
76 provider_extra: Some(serde_json::json!({"layer": "base", "political_view": "ARG"})),
77 };
78 let json = serde_json::to_string(&options).unwrap();
79 let back: TileOptions = serde_json::from_str(&json).unwrap();
80 assert_eq!(back.format, Some("json".to_string()));
81 assert!(back.provider_extra.is_some());
82 }
83
84 #[test]
87 fn test_tile_response_empty_data() {
88 let response = TileResponse::new(vec![], None);
89 assert!(response.data.is_empty());
90 assert!(response.content_type.is_none());
91 }
92
93 #[test]
94 fn test_tile_response_no_content_type() {
95 let response = TileResponse::new(vec![0x1A, 0x2B, 0x3C, 0x4D], None);
96 assert_eq!(response.data.len(), 4);
97 assert!(response.content_type.is_none());
98 }
99
100 #[test]
101 fn test_tile_response_json_content_type() {
102 let response = TileResponse::new(
103 b"{\"tile\":1}".to_vec(),
104 Some("application/json".to_string()),
105 );
106 assert_eq!(response.content_type, Some("application/json".to_string()));
107 }
108
109 #[test]
110 fn test_tile_response_large_data() {
111 let data: Vec<u8> = (0..8192).map(|i| (i % 256) as u8).collect();
112 let response = TileResponse::new(data, Some("application/x-protobuf".to_string()));
113 assert_eq!(response.data.len(), 8192);
114 }
115
116 #[test]
119 fn test_tile_response_clone() {
120 let response = TileResponse::new(vec![1, 2, 3], Some("test/type".to_string()));
121 let cloned = response.clone();
122 assert_eq!(cloned.data, response.data);
123 assert_eq!(cloned.content_type, response.content_type);
124 }
125
126 #[test]
129 fn test_tile_response_debug() {
130 let response = TileResponse::new(vec![1], Some("application/json".to_string()));
131 let debug_str = format!("{:?}", response);
132 assert!(debug_str.contains("TileResponse"));
133 }
134}