everymap_core/domains/
imaging.rs1use crate::error::EveryMapResult;
2use crate::types::Coordinate;
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Default, Serialize, Deserialize)]
8pub struct ImageOptions {
9 pub format: Option<String>,
11 pub language: Option<String>,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
15 pub provider_extra: Option<serde_json::Value>,
16}
17
18#[derive(Debug, Clone)]
20pub struct ImageResponse {
21 pub data: Vec<u8>,
22 pub content_type: Option<String>,
23}
24
25impl ImageResponse {
26 pub fn new(data: Vec<u8>, content_type: Option<String>) -> Self {
28 Self { data, content_type }
29 }
30}
31
32#[async_trait]
33pub trait MapImageProvider: Send + Sync {
34 async fn get_image(
35 &self,
36 center: &Coordinate,
37 zoom: u32,
38 size: (u32, u32),
39 options: &ImageOptions,
40 ) -> EveryMapResult<ImageResponse>;
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_image_options_default() {
49 let options = ImageOptions::default();
50 assert!(options.format.is_none());
51 assert!(options.language.is_none());
52 assert!(options.provider_extra.is_none());
53 }
54
55 #[test]
56 fn test_image_options_with_fields() {
57 let options = ImageOptions {
58 format: Some("png".to_string()),
59 language: Some("en".to_string()),
60 provider_extra: Some(serde_json::json!({"style": "default"})),
61 };
62 assert_eq!(options.format, Some("png".to_string()));
63 }
64
65 #[test]
66 fn test_image_response_construction() {
67 let response =
68 ImageResponse::new(vec![0x89, 0x50, 0x4E, 0x47], Some("image/png".to_string()));
69 assert_eq!(response.data.len(), 4);
70 assert_eq!(response.content_type, Some("image/png".to_string()));
71 }
72
73 #[test]
76 fn test_image_options_serde_roundtrip() {
77 let options = ImageOptions {
78 format: Some("jpg".to_string()),
79 language: Some("ja".to_string()),
80 provider_extra: Some(
81 serde_json::json!({"maptype": "satellite", "markers": [{"lat": 35.6762, "lng": 139.6503}]}),
82 ),
83 };
84 let json = serde_json::to_string(&options).unwrap();
85 let back: ImageOptions = serde_json::from_str(&json).unwrap();
86 assert_eq!(back.format, Some("jpg".to_string()));
87 assert!(back.provider_extra.is_some());
88 }
89
90 #[test]
93 fn test_image_response_empty_data() {
94 let response = ImageResponse::new(vec![], None);
95 assert!(response.data.is_empty());
96 assert!(response.content_type.is_none());
97 }
98
99 #[test]
100 fn test_image_response_no_content_type() {
101 let response = ImageResponse::new(vec![0xFF, 0xD8, 0xFF], None);
102 assert_eq!(response.data.len(), 3);
103 assert!(response.content_type.is_none());
104 }
105
106 #[test]
107 fn test_image_response_jpeg_content_type() {
108 let response =
109 ImageResponse::new(vec![0xFF, 0xD8, 0xFF, 0xE0], Some("image/jpeg".to_string()));
110 assert_eq!(response.content_type, Some("image/jpeg".to_string()));
111 }
112
113 #[test]
114 fn test_image_response_large_data() {
115 let data: Vec<u8> = (0..1024).map(|i| (i % 256) as u8).collect();
116 let response = ImageResponse::new(data, Some("image/png".to_string()));
117 assert_eq!(response.data.len(), 1024);
118 }
119
120 #[test]
123 fn test_image_response_clone() {
124 let response = ImageResponse::new(vec![1, 2, 3], Some("image/png".to_string()));
125 let cloned = response.clone();
126 assert_eq!(cloned.data, response.data);
127 assert_eq!(cloned.content_type, response.content_type);
128 }
129}