1use std::ptr;
2
3pub(crate) use maplibre_core::style::{
4 GeoJsonSourceOptionsNativeExt, NativeGeoJsonSourceOptions, NativeStyleImageOptions,
5 NativeTileSourceOptions, NativeTileUrls, StyleImageOptionsNativeExt,
6 TileSourceOptionsNativeExt,
7};
8pub use maplibre_core::{
9 GeoJsonSourceOptions, ImageContent, ImageStretch, LocationIndicatorImageKind,
10 RasterDemEncoding, SourceInfo, SourceType, StyleImage, StyleImageInfo, StyleImageOptions,
11 StyleImageTextFit, StyleLayerVisibility, StyleTransitionOptions, TileJsonInfo, TileScheme,
12 TileSourceOptions, VectorTileEncoding,
13};
14use maplibre_native_ffi_core as maplibre_core;
15use maplibre_native_ffi_core::ptr::const_ptr_or_null;
16use maplibre_native_ffi_core::query::FeatureStateSelectorNativeExt;
17use maplibre_native_ffi_core::values::lat_lngs_to_native;
18use maplibre_native_ffi_sys as sys;
19
20use crate::custom_geometry::{CanonicalTileId, CustomGeometrySourceState};
21use crate::custom_mvt_vector::CustomMvtVectorSourceState;
22use crate::render::PremultipliedRgba8Image;
23use crate::values::NativeValue;
24use crate::{
25 CustomGeometrySourceOptions, CustomMvtVectorSourceOptions, Error, ErrorKind,
26 FeatureStateSelector, LatLng, LatLngBounds, Result,
27};
28
29impl super::MapHandle {
30 pub fn set_style_url(&self, url: &str) -> Result<()> {
36 let map = self.inner.native()?;
37 let url = maplibre_core::string::c_string(url)?;
38 maplibre_core::check(unsafe { sys::mln_map_set_style_url(map, url.as_ptr()) })?;
41 Ok(())
42 }
43
44 pub fn set_style_json(&self, json: &[u8]) -> Result<()> {
49 let map = self.inner.native()?;
50 let json = maplibre_core::string::buffer_view(json);
51 maplibre_core::check(unsafe { sys::mln_map_set_style_json(map, json) })
55 }
56
57 pub fn set_feature_state(&self, selector: &FeatureStateSelector, state: &[u8]) -> Result<()> {
59 let map = self.inner.native()?;
60 let selector = selector.to_native();
61 let state = maplibre_core::string::buffer_view(state);
62 maplibre_core::check(unsafe {
64 sys::mln_map_set_feature_state(map, selector.as_ptr(), state)
65 })
66 }
67
68 pub fn get_feature_state(&self, selector: &FeatureStateSelector) -> Result<Vec<u8>> {
70 let map = self.inner.native()?;
71 let selector = selector.to_native();
72 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
73 maplibre_core::check(unsafe {
75 sys::mln_map_get_feature_state(map, selector.as_ptr(), out.as_mut_ptr())
76 })?;
77 unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }
79 }
80
81 pub fn remove_feature_state(&self, selector: &FeatureStateSelector) -> Result<()> {
83 let map = self.inner.native()?;
84 let selector = selector.to_native();
85 maplibre_core::check(unsafe { sys::mln_map_remove_feature_state(map, selector.as_ptr()) })
87 }
88
89 pub fn loaded_style_json(&self) -> Result<Vec<u8>> {
94 let map = self.inner.native()?;
95 unsafe {
98 copy_bytes(|text, capacity, out_size| {
99 sys::mln_map_copy_loaded_style_json(map, text, capacity, out_size)
100 })
101 }
102 }
103
104 pub fn style_url(&self) -> Result<String> {
111 let map = self.inner.native()?;
112 unsafe {
115 copy_text(|url, capacity, out_size| {
116 sys::mln_map_copy_style_url(map, url, capacity, out_size)
117 })
118 }
119 }
120
121 pub fn add_custom_geometry_source(
129 &self,
130 source_id: &str,
131 options: CustomGeometrySourceOptions,
132 ) -> Result<()> {
133 let map = self.inner.native()?;
134 let source_id_view = maplibre_core::string::string_view(source_id);
135 let state = CustomGeometrySourceState::new(options);
136 let descriptor = state.descriptor();
137 let state = Box::into_raw(state);
140 let status = unsafe {
143 sys::mln_map_add_custom_geometry_source(map, source_id_view.raw(), &descriptor)
144 };
145 if let Err(error) = maplibre_core::check(status) {
146 drop(unsafe { Box::from_raw(state) });
149 return Err(error);
150 }
151 Ok(())
152 }
153
154 pub fn set_custom_geometry_source_tile_data(
156 &self,
157 source_id: &str,
158 tile_id: CanonicalTileId,
159 data: &[u8],
160 ) -> Result<()> {
161 let map = self.inner.native()?;
162 let source_id = maplibre_core::string::string_view(source_id);
163 let data = maplibre_core::string::buffer_view(data);
164 maplibre_core::check(unsafe {
167 sys::mln_map_set_custom_geometry_source_tile_data(
168 map,
169 source_id.raw(),
170 tile_id.to_native(),
171 data,
172 )
173 })
174 }
175
176 pub fn invalidate_custom_geometry_source_tile(
178 &self,
179 source_id: &str,
180 tile_id: CanonicalTileId,
181 ) -> Result<()> {
182 let map = self.inner.native()?;
183 let source_id = maplibre_core::string::string_view(source_id);
184 maplibre_core::check(unsafe {
187 sys::mln_map_invalidate_custom_geometry_source_tile(
188 map,
189 source_id.raw(),
190 tile_id.to_native(),
191 )
192 })
193 }
194
195 pub fn invalidate_custom_geometry_source_region(
197 &self,
198 source_id: &str,
199 bounds: LatLngBounds,
200 ) -> Result<()> {
201 let map = self.inner.native()?;
202 let source_id = maplibre_core::string::string_view(source_id);
203 maplibre_core::check(unsafe {
206 sys::mln_map_invalidate_custom_geometry_source_region(
207 map,
208 source_id.raw(),
209 bounds.to_native(),
210 )
211 })
212 }
213
214 pub fn add_custom_mvt_vector_source(
222 &self,
223 source_id: &str,
224 options: CustomMvtVectorSourceOptions,
225 ) -> Result<()> {
226 let map = self.inner.native()?;
227 let source_id_view = maplibre_core::string::string_view(source_id);
228 let state = CustomMvtVectorSourceState::new(options);
229 let descriptor = state.descriptor();
230 let state = Box::into_raw(state);
233 let status = unsafe {
236 sys::mln_map_add_custom_mvt_vector_source(map, source_id_view.raw(), &descriptor)
237 };
238 if let Err(error) = maplibre_core::check(status) {
239 drop(unsafe { Box::from_raw(state) });
242 return Err(error);
243 }
244 Ok(())
245 }
246
247 pub fn set_custom_mvt_vector_source_tile_data(
252 &self,
253 source_id: &str,
254 tile_id: CanonicalTileId,
255 data: &[u8],
256 ) -> Result<()> {
257 let map = self.inner.native()?;
258 let source_id = maplibre_core::string::string_view(source_id);
259 let data = maplibre_core::string::buffer_view(data);
260 maplibre_core::check(unsafe {
263 sys::mln_map_set_custom_mvt_vector_source_tile_data(
264 map,
265 source_id.raw(),
266 tile_id.to_native(),
267 data,
268 )
269 })
270 }
271
272 pub fn set_custom_mvt_vector_source_tile_error(
274 &self,
275 source_id: &str,
276 tile_id: CanonicalTileId,
277 message: &str,
278 ) -> Result<()> {
279 let map = self.inner.native()?;
280 let source_id = maplibre_core::string::string_view(source_id);
281 let message = maplibre_core::string::string_view(message);
282 maplibre_core::check(unsafe {
285 sys::mln_map_set_custom_mvt_vector_source_tile_error(
286 map,
287 source_id.raw(),
288 tile_id.to_native(),
289 message.raw(),
290 )
291 })
292 }
293
294 pub fn invalidate_custom_mvt_vector_source_tile(
296 &self,
297 source_id: &str,
298 tile_id: CanonicalTileId,
299 ) -> Result<()> {
300 let map = self.inner.native()?;
301 let source_id = maplibre_core::string::string_view(source_id);
302 maplibre_core::check(unsafe {
305 sys::mln_map_invalidate_custom_mvt_vector_source_tile(
306 map,
307 source_id.raw(),
308 tile_id.to_native(),
309 )
310 })
311 }
312
313 pub fn add_style_source_json(&self, source_id: &str, source_json: &[u8]) -> Result<()> {
315 let map = self.inner.native()?;
316 let source_id = maplibre_core::string::string_view(source_id);
317 let source_json = maplibre_core::string::buffer_view(source_json);
318 maplibre_core::check(unsafe {
321 sys::mln_map_add_style_source_json(map, source_id.raw(), source_json)
322 })
323 }
324
325 pub fn add_vector_source_url(
327 &self,
328 source_id: &str,
329 url: &str,
330 options: Option<&TileSourceOptions>,
331 ) -> Result<()> {
332 let map = self.inner.native()?;
333 let source_id = maplibre_core::string::string_view(source_id);
334 let url = maplibre_core::string::string_view(url);
335 let options = options.map(TileSourceOptions::to_native);
336 let options_ptr = options
337 .as_ref()
338 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
339 maplibre_core::check(unsafe {
342 sys::mln_map_add_vector_source_url(map, source_id.raw(), url.raw(), options_ptr)
343 })
344 }
345
346 pub fn add_vector_source_tiles<S: AsRef<str>>(
348 &self,
349 source_id: &str,
350 tiles: &[S],
351 options: Option<&TileSourceOptions>,
352 ) -> Result<()> {
353 let map = self.inner.native()?;
354 let source_id = maplibre_core::string::string_view(source_id);
355 let raw_tiles = NativeTileUrls::new(tiles);
356 let options = options.map(TileSourceOptions::to_native);
357 let options_ptr = options
358 .as_ref()
359 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
360 maplibre_core::check(unsafe {
364 sys::mln_map_add_vector_source_tiles(
365 map,
366 source_id.raw(),
367 raw_tiles.as_ptr(),
368 raw_tiles.len(),
369 options_ptr,
370 )
371 })
372 }
373
374 pub fn add_raster_source_url(
376 &self,
377 source_id: &str,
378 url: &str,
379 options: Option<&TileSourceOptions>,
380 ) -> Result<()> {
381 let map = self.inner.native()?;
382 let source_id = maplibre_core::string::string_view(source_id);
383 let url = maplibre_core::string::string_view(url);
384 let options = options.map(TileSourceOptions::to_native);
385 let options_ptr = options
386 .as_ref()
387 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
388 maplibre_core::check(unsafe {
391 sys::mln_map_add_raster_source_url(map, source_id.raw(), url.raw(), options_ptr)
392 })
393 }
394
395 pub fn add_raster_source_tiles<S: AsRef<str>>(
397 &self,
398 source_id: &str,
399 tiles: &[S],
400 options: Option<&TileSourceOptions>,
401 ) -> Result<()> {
402 let map = self.inner.native()?;
403 let source_id = maplibre_core::string::string_view(source_id);
404 let raw_tiles = NativeTileUrls::new(tiles);
405 let options = options.map(TileSourceOptions::to_native);
406 let options_ptr = options
407 .as_ref()
408 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
409 maplibre_core::check(unsafe {
413 sys::mln_map_add_raster_source_tiles(
414 map,
415 source_id.raw(),
416 raw_tiles.as_ptr(),
417 raw_tiles.len(),
418 options_ptr,
419 )
420 })
421 }
422
423 pub fn add_raster_dem_source_url(
425 &self,
426 source_id: &str,
427 url: &str,
428 options: Option<&TileSourceOptions>,
429 ) -> Result<()> {
430 let map = self.inner.native()?;
431 let source_id = maplibre_core::string::string_view(source_id);
432 let url = maplibre_core::string::string_view(url);
433 let options = options.map(TileSourceOptions::to_native);
434 let options_ptr = options
435 .as_ref()
436 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
437 maplibre_core::check(unsafe {
440 sys::mln_map_add_raster_dem_source_url(map, source_id.raw(), url.raw(), options_ptr)
441 })
442 }
443
444 pub fn add_raster_dem_source_tiles<S: AsRef<str>>(
446 &self,
447 source_id: &str,
448 tiles: &[S],
449 options: Option<&TileSourceOptions>,
450 ) -> Result<()> {
451 let map = self.inner.native()?;
452 let source_id = maplibre_core::string::string_view(source_id);
453 let raw_tiles = NativeTileUrls::new(tiles);
454 let options = options.map(TileSourceOptions::to_native);
455 let options_ptr = options
456 .as_ref()
457 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
458 maplibre_core::check(unsafe {
462 sys::mln_map_add_raster_dem_source_tiles(
463 map,
464 source_id.raw(),
465 raw_tiles.as_ptr(),
466 raw_tiles.len(),
467 options_ptr,
468 )
469 })
470 }
471
472 pub fn add_image_source_url(
478 &self,
479 source_id: &str,
480 coordinates: &[LatLng; 4],
481 url: &str,
482 ) -> Result<()> {
483 let map = self.inner.native()?;
484 let source_id = maplibre_core::string::string_view(source_id);
485 let coordinates = lat_lngs_to_native(coordinates);
486 let url = maplibre_core::string::string_view(url);
487 maplibre_core::check(unsafe {
491 sys::mln_map_add_image_source_url(
492 map,
493 source_id.raw(),
494 const_ptr_or_null(&coordinates),
495 coordinates.len(),
496 url.raw(),
497 )
498 })
499 }
500
501 pub fn add_image_source_image(
507 &self,
508 source_id: &str,
509 coordinates: &[LatLng; 4],
510 image: &PremultipliedRgba8Image,
511 ) -> Result<()> {
512 let map = self.inner.native()?;
513 let source_id = maplibre_core::string::string_view(source_id);
514 let coordinates = lat_lngs_to_native(coordinates);
515 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
516 maplibre_core::check(unsafe {
520 sys::mln_map_add_image_source_image(
521 map,
522 source_id.raw(),
523 const_ptr_or_null(&coordinates),
524 coordinates.len(),
525 &image,
526 )
527 })
528 }
529
530 pub fn set_image_source_url(&self, source_id: &str, url: &str) -> Result<()> {
532 let map = self.inner.native()?;
533 let source_id = maplibre_core::string::string_view(source_id);
534 let url = maplibre_core::string::string_view(url);
535 maplibre_core::check(unsafe {
538 sys::mln_map_set_image_source_url(map, source_id.raw(), url.raw())
539 })
540 }
541
542 pub fn set_image_source_image(
544 &self,
545 source_id: &str,
546 image: &PremultipliedRgba8Image,
547 ) -> Result<()> {
548 let map = self.inner.native()?;
549 let source_id = maplibre_core::string::string_view(source_id);
550 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
551 maplibre_core::check(unsafe {
554 sys::mln_map_set_image_source_image(map, source_id.raw(), &image)
555 })
556 }
557
558 pub fn set_image_source_coordinates(
564 &self,
565 source_id: &str,
566 coordinates: &[LatLng; 4],
567 ) -> Result<()> {
568 let map = self.inner.native()?;
569 let source_id = maplibre_core::string::string_view(source_id);
570 let coordinates = lat_lngs_to_native(coordinates);
571 maplibre_core::check(unsafe {
575 sys::mln_map_set_image_source_coordinates(
576 map,
577 source_id.raw(),
578 const_ptr_or_null(&coordinates),
579 coordinates.len(),
580 )
581 })
582 }
583
584 pub fn image_source_coordinates(&self, source_id: &str) -> Result<Option<[LatLng; 4]>> {
586 let map = self.inner.native()?;
587 let source_id = maplibre_core::string::string_view(source_id);
588 let mut coordinates = [sys::mln_lat_lng {
589 latitude: 0.0,
590 longitude: 0.0,
591 }; 4];
592 let mut coordinate_count = 0;
593 let mut found = false;
594 maplibre_core::check(unsafe {
598 sys::mln_map_get_image_source_coordinates(
599 map,
600 source_id.raw(),
601 coordinates.as_mut_ptr(),
602 coordinates.len(),
603 &mut coordinate_count,
604 &mut found,
605 )
606 })?;
607 if !found {
608 return Ok(None);
609 }
610 if coordinate_count != coordinates.len() {
611 return Err(Error::new(
612 ErrorKind::NativeError,
613 None,
614 "native image source coordinate count did not match Rust image source invariant",
615 ));
616 }
617 Ok(Some(coordinates.map(LatLng::from_native)))
618 }
619
620 pub fn remove_style_source(&self, source_id: &str) -> Result<bool> {
625 let map = self.inner.native()?;
626 let source_id = maplibre_core::string::string_view(source_id);
627 let mut removed = false;
628 maplibre_core::check(unsafe {
631 sys::mln_map_remove_style_source(map, source_id.raw(), &mut removed)
632 })?;
633 Ok(removed)
634 }
635
636 pub fn style_source_exists(&self, source_id: &str) -> Result<bool> {
638 let map = self.inner.native()?;
639 let source_id = maplibre_core::string::string_view(source_id);
640 let mut exists = false;
641 maplibre_core::check(unsafe {
644 sys::mln_map_style_source_exists(map, source_id.raw(), &mut exists)
645 })?;
646 Ok(exists)
647 }
648
649 pub fn set_style_image(
651 &self,
652 image_id: &str,
653 image: &PremultipliedRgba8Image,
654 options: Option<&StyleImageOptions>,
655 ) -> Result<()> {
656 let map = self.inner.native()?;
657 let image_id = maplibre_core::string::string_view(image_id);
658 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
659 let options = options.map(StyleImageOptions::to_native);
660 let options_ptr = options
661 .as_ref()
662 .map_or(ptr::null(), NativeStyleImageOptions::as_ptr);
663 maplibre_core::check(unsafe {
667 sys::mln_map_set_style_image(map, image_id.raw(), &image, options_ptr)
668 })
669 }
670
671 pub fn remove_style_image(&self, image_id: &str) -> Result<bool> {
675 let map = self.inner.native()?;
676 let image_id = maplibre_core::string::string_view(image_id);
677 let mut removed = false;
678 maplibre_core::check(unsafe {
681 sys::mln_map_remove_style_image(map, image_id.raw(), &mut removed)
682 })?;
683 Ok(removed)
684 }
685
686 pub fn style_image_exists(&self, image_id: &str) -> Result<bool> {
688 let map = self.inner.native()?;
689 let image_id = maplibre_core::string::string_view(image_id);
690 let mut exists = false;
691 maplibre_core::check(unsafe {
694 sys::mln_map_style_image_exists(map, image_id.raw(), &mut exists)
695 })?;
696 Ok(exists)
697 }
698
699 pub fn style_image_info(&self, image_id: &str) -> Result<Option<StyleImageInfo>> {
701 let map = self.inner.native()?;
702 let image_id = maplibre_core::string::string_view(image_id);
703 let mut info = maplibre_core::style::empty_style_image_info();
704 let mut found = false;
705 maplibre_core::check(unsafe {
709 sys::mln_map_get_style_image_info(map, image_id.raw(), &mut info, &mut found)
710 })?;
711 Ok(found.then(|| maplibre_core::values::style_image_info_from_native(&info)))
712 }
713
714 pub fn copy_style_image_premultiplied_rgba8(
716 &self,
717 image_id: &str,
718 ) -> Result<Option<StyleImage>> {
719 let map = self.inner.native()?;
720 let image_id = maplibre_core::string::string_view(image_id);
721 let mut raw_info = maplibre_core::style::empty_style_image_info();
722 let mut info_found = false;
723 maplibre_core::check(unsafe {
727 sys::mln_map_get_style_image_info(map, image_id.raw(), &mut raw_info, &mut info_found)
728 })?;
729 if !info_found {
730 return Ok(None);
731 }
732 let info = maplibre_core::values::style_image_info_from_native(&raw_info);
733
734 let mut data = vec![0u8; info.byte_length];
735 let mut copied_size = 0;
736 let mut found = false;
737 let pixels = if data.is_empty() {
738 ptr::null_mut()
739 } else {
740 data.as_mut_ptr()
741 };
742 maplibre_core::check(unsafe {
746 sys::mln_map_copy_style_image_premultiplied_rgba8(
747 map,
748 image_id.raw(),
749 pixels,
750 data.len(),
751 &mut copied_size,
752 &mut found,
753 )
754 })?;
755 if !found {
756 return Ok(None);
757 }
758 maplibre_core::style::style_image_from_copied_premultiplied_rgba8(info, data, copied_size)
759 .map(Some)
760 }
761
762 pub fn style_source_type(&self, source_id: &str) -> Result<Option<SourceType>> {
764 let map = self.inner.native()?;
765 let source_id = maplibre_core::string::string_view(source_id);
766 let mut raw_source_type = sys::MLN_STYLE_SOURCE_TYPE_UNKNOWN;
767 let mut found = false;
768 maplibre_core::check(unsafe {
771 sys::mln_map_get_style_source_type(
772 map,
773 source_id.raw(),
774 &mut raw_source_type,
775 &mut found,
776 )
777 })?;
778 Ok(found.then(|| SourceType::from_raw(raw_source_type)))
779 }
780
781 pub fn style_source_info(&self, source_id: &str) -> Result<Option<SourceInfo>> {
783 let map = self.inner.native()?;
784 let source_id = maplibre_core::string::string_view(source_id);
785 let mut info = maplibre_core::style::empty_style_source_info();
786 let mut found = false;
787 maplibre_core::check(unsafe {
791 sys::mln_map_get_style_source_info(map, source_id.raw(), &mut info, &mut found)
792 })?;
793 if !found {
794 return Ok(None);
795 }
796
797 let attribution = if info.has_attribution {
798 match self.copy_style_source_attribution(map, source_id.raw(), info.attribution_size)? {
799 Some(attribution) => Some(attribution),
800 None => return Ok(None),
801 }
802 } else {
803 None
804 };
805
806 let url = if info.fields & sys::MLN_STYLE_SOURCE_INFO_URL != 0 {
807 match self.copy_style_source_url(map, source_id.raw(), info.url_size)? {
808 Some(url) => Some(url),
809 None => return Ok(None),
810 }
811 } else {
812 None
813 };
814
815 let tiles = if info.fields & sys::MLN_STYLE_SOURCE_INFO_TILEJSON != 0 {
816 match self.copy_style_source_tile_urls(map, source_id.raw())? {
817 Some(tiles) => tiles,
818 None => return Ok(None),
819 }
820 } else {
821 Vec::new()
822 };
823
824 Ok(Some(maplibre_core::style::style_source_info_from_native(
825 &info,
826 attribution,
827 url,
828 tiles,
829 )))
830 }
831
832 pub fn set_style_source_volatile(&self, source_id: &str, is_volatile: bool) -> Result<()> {
838 let map = self.inner.native()?;
839 let source_id = maplibre_core::string::string_view(source_id);
840 maplibre_core::check(unsafe {
843 sys::mln_map_set_style_source_volatile(map, source_id.raw(), is_volatile)
844 })
845 }
846
847 fn copy_style_source_attribution(
848 &self,
849 map: sys::mln_map,
850 source_id: sys::mln_buffer_view,
851 attribution_size: usize,
852 ) -> Result<Option<String>> {
853 if attribution_size == 0 {
854 let mut copied_size = 0;
855 let mut found = false;
856 maplibre_core::check(unsafe {
860 sys::mln_map_copy_style_source_attribution(
861 map,
862 source_id,
863 ptr::null_mut(),
864 0,
865 &mut copied_size,
866 &mut found,
867 )
868 })?;
869 return Ok(found.then(String::new));
870 }
871
872 let mut buffer = vec![0u8; attribution_size];
873 let mut copied_size = 0;
874 let mut found = false;
875 maplibre_core::check(unsafe {
879 sys::mln_map_copy_style_source_attribution(
880 map,
881 source_id,
882 buffer.as_mut_ptr().cast(),
883 buffer.len(),
884 &mut copied_size,
885 &mut found,
886 )
887 })?;
888 if !found {
889 return Ok(None);
890 }
891 if copied_size > buffer.len() {
892 return Err(Error::new(
893 ErrorKind::NativeError,
894 None,
895 "native style source attribution size exceeded caller buffer",
896 ));
897 }
898 buffer.truncate(copied_size);
899 String::from_utf8(buffer).map(Some).map_err(|error| {
900 Error::invalid_argument(format!(
901 "native style source attribution was not valid UTF-8: {error}"
902 ))
903 })
904 }
905
906 fn copy_style_source_url(
907 &self,
908 map: sys::mln_map,
909 source_id: sys::mln_buffer_view,
910 url_size: usize,
911 ) -> Result<Option<String>> {
912 let mut buffer = vec![0u8; url_size];
913 let mut copied_size = 0;
914 let mut found = false;
915 maplibre_core::check(unsafe {
919 sys::mln_map_copy_style_source_url(
920 map,
921 source_id,
922 if buffer.is_empty() {
923 ptr::null_mut()
924 } else {
925 buffer.as_mut_ptr().cast()
926 },
927 buffer.len(),
928 &mut copied_size,
929 &mut found,
930 )
931 })?;
932 if !found {
933 return Ok(None);
934 }
935 if copied_size > buffer.len() {
936 return Err(Error::new(
937 ErrorKind::NativeError,
938 None,
939 "native style source URL size exceeded caller buffer",
940 ));
941 }
942 buffer.truncate(copied_size);
943 String::from_utf8(buffer).map(Some).map_err(|error| {
944 Error::invalid_argument(format!(
945 "native style source URL was not valid UTF-8: {error}"
946 ))
947 })
948 }
949
950 fn copy_style_source_tile_urls(
951 &self,
952 map: sys::mln_map,
953 source_id: sys::mln_buffer_view,
954 ) -> Result<Option<Vec<String>>> {
955 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_string_list>::new();
956 let mut found = false;
957 maplibre_core::check(unsafe {
960 sys::mln_map_get_style_source_tile_urls(map, source_id, out.as_mut_ptr(), &mut found)
961 })?;
962 if !found {
963 return Ok(None);
964 }
965 unsafe {
968 maplibre_core::style::copy_style_string_list(out.into_live("mln_style_string_list")?)
969 .map(Some)
970 }
971 }
972
973 pub fn add_geojson_source_url(
976 &self,
977 source_id: &str,
978 url: &str,
979 options: Option<&GeoJsonSourceOptions>,
980 ) -> Result<()> {
981 let map = self.inner.native()?;
982 let source_id = maplibre_core::string::string_view(source_id);
983 let url = maplibre_core::string::string_view(url);
984 let options = options
985 .map(GeoJsonSourceOptions::try_to_native)
986 .transpose()?;
987 let options_ptr = options
988 .as_ref()
989 .map_or(ptr::null(), NativeGeoJsonSourceOptions::as_ptr);
990 maplibre_core::check(unsafe {
994 sys::mln_map_add_geojson_source_url(map, source_id.raw(), url.raw(), options_ptr)
995 })
996 }
997
998 pub fn add_geojson_source_data(
1003 &self,
1004 source_id: &str,
1005 data: &crate::GeoJsonSourceDataHandle,
1006 ) -> Result<()> {
1007 let map = self.inner.native()?;
1008 let source_id = maplibre_core::string::string_view(source_id);
1009 maplibre_core::check(unsafe {
1012 sys::mln_map_add_geojson_source_data(map, source_id.raw(), data.native())
1013 })
1014 }
1015
1016 pub fn set_geojson_source_url(&self, source_id: &str, url: &str) -> Result<()> {
1020 let map = self.inner.native()?;
1021 let source_id = maplibre_core::string::string_view(source_id);
1022 let url = maplibre_core::string::string_view(url);
1023 maplibre_core::check(unsafe {
1025 sys::mln_map_set_geojson_source_url(map, source_id.raw(), url.raw())
1026 })
1027 }
1028
1029 pub fn set_geojson_source_data(
1036 &self,
1037 source_id: &str,
1038 data: &crate::GeoJsonSourceDataHandle,
1039 ) -> Result<()> {
1040 let map = self.inner.native()?;
1041 let source_id = maplibre_core::string::string_view(source_id);
1042 maplibre_core::check(unsafe {
1045 sys::mln_map_set_geojson_source_data(map, source_id.raw(), data.native())
1046 })
1047 }
1048
1049 pub fn set_geojson_source_synchronous_tiling(
1056 &self,
1057 source_id: &str,
1058 enabled: bool,
1059 ) -> Result<()> {
1060 let map = self.inner.native()?;
1061 let source_id = maplibre_core::string::string_view(source_id);
1062 maplibre_core::check(unsafe {
1064 sys::mln_map_set_geojson_source_synchronous_tiling(map, source_id.raw(), enabled)
1065 })
1066 }
1067
1068 pub fn add_style_layer_json(
1070 &self,
1071 layer_json: &[u8],
1072 before_layer_id: Option<&str>,
1073 ) -> Result<()> {
1074 let map = self.inner.native()?;
1075 let layer_json = maplibre_core::string::buffer_view(layer_json);
1076 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
1077 maplibre_core::check(unsafe {
1080 sys::mln_map_add_style_layer_json(map, layer_json, before_layer_id.raw())
1081 })
1082 }
1083
1084 pub fn add_hillshade_layer(
1086 &self,
1087 layer_id: &str,
1088 source_id: &str,
1089 before_layer_id: Option<&str>,
1090 ) -> Result<()> {
1091 let map = self.inner.native()?;
1092 let layer_id = maplibre_core::string::string_view(layer_id);
1093 let source_id = maplibre_core::string::string_view(source_id);
1094 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
1095 maplibre_core::check(unsafe {
1097 sys::mln_map_add_hillshade_layer(
1098 map,
1099 layer_id.raw(),
1100 source_id.raw(),
1101 before_layer_id.raw(),
1102 )
1103 })
1104 }
1105
1106 pub fn add_color_relief_layer(
1108 &self,
1109 layer_id: &str,
1110 source_id: &str,
1111 before_layer_id: Option<&str>,
1112 ) -> Result<()> {
1113 let map = self.inner.native()?;
1114 let layer_id = maplibre_core::string::string_view(layer_id);
1115 let source_id = maplibre_core::string::string_view(source_id);
1116 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
1117 maplibre_core::check(unsafe {
1119 sys::mln_map_add_color_relief_layer(
1120 map,
1121 layer_id.raw(),
1122 source_id.raw(),
1123 before_layer_id.raw(),
1124 )
1125 })
1126 }
1127
1128 pub fn add_location_indicator_layer(
1130 &self,
1131 layer_id: &str,
1132 before_layer_id: Option<&str>,
1133 ) -> Result<()> {
1134 let map = self.inner.native()?;
1135 let layer_id = maplibre_core::string::string_view(layer_id);
1136 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
1137 maplibre_core::check(unsafe {
1139 sys::mln_map_add_location_indicator_layer(map, layer_id.raw(), before_layer_id.raw())
1140 })
1141 }
1142
1143 pub fn set_location_indicator_location(
1145 &self,
1146 layer_id: &str,
1147 coordinate: LatLng,
1148 altitude: f64,
1149 ) -> Result<()> {
1150 let map = self.inner.native()?;
1151 let layer_id = maplibre_core::string::string_view(layer_id);
1152 maplibre_core::check(unsafe {
1155 sys::mln_map_set_location_indicator_location(
1156 map,
1157 layer_id.raw(),
1158 coordinate.to_native(),
1159 altitude,
1160 )
1161 })
1162 }
1163
1164 pub fn set_location_indicator_bearing(&self, layer_id: &str, bearing: f64) -> Result<()> {
1166 let map = self.inner.native()?;
1167 let layer_id = maplibre_core::string::string_view(layer_id);
1168 maplibre_core::check(unsafe {
1170 sys::mln_map_set_location_indicator_bearing(map, layer_id.raw(), bearing)
1171 })
1172 }
1173
1174 pub fn set_location_indicator_accuracy_radius(
1176 &self,
1177 layer_id: &str,
1178 radius: f64,
1179 ) -> Result<()> {
1180 let map = self.inner.native()?;
1181 let layer_id = maplibre_core::string::string_view(layer_id);
1182 maplibre_core::check(unsafe {
1184 sys::mln_map_set_location_indicator_accuracy_radius(map, layer_id.raw(), radius)
1185 })
1186 }
1187
1188 pub fn set_location_indicator_image_name(
1190 &self,
1191 layer_id: &str,
1192 image_kind: LocationIndicatorImageKind,
1193 image_id: &str,
1194 ) -> Result<()> {
1195 let map = self.inner.native()?;
1196 let layer_id = maplibre_core::string::string_view(layer_id);
1197 let image_id = maplibre_core::string::string_view(image_id);
1198 maplibre_core::check(unsafe {
1201 sys::mln_map_set_location_indicator_image_name(
1202 map,
1203 layer_id.raw(),
1204 image_kind.raw_value(),
1205 image_id.raw(),
1206 )
1207 })
1208 }
1209
1210 pub fn style_layer_json(&self, layer_id: &str) -> Result<Option<Vec<u8>>> {
1212 let map = self.inner.native()?;
1213 let layer_id = maplibre_core::string::string_view(layer_id);
1214 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1215 let mut found = false;
1216 maplibre_core::check(unsafe {
1219 sys::mln_map_get_style_layer_json(map, layer_id.raw(), out.as_mut_ptr(), &mut found)
1220 })?;
1221 if !found {
1222 return Ok(None);
1223 }
1224 unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }.map(Some)
1226 }
1227
1228 pub fn set_style_light_json(&self, light_json: &[u8]) -> Result<()> {
1230 let map = self.inner.native()?;
1231 let light_json = maplibre_core::string::buffer_view(light_json);
1232 maplibre_core::check(unsafe { sys::mln_map_set_style_light_json(map, light_json) })
1234 }
1235
1236 pub fn set_style_light_property(&self, property_name: &str, value: &[u8]) -> Result<()> {
1238 let map = self.inner.native()?;
1239 let property_name = maplibre_core::string::string_view(property_name);
1240 let value = maplibre_core::string::buffer_view(value);
1241 maplibre_core::check(unsafe {
1243 sys::mln_map_set_style_light_property(map, property_name.raw(), value)
1244 })
1245 }
1246
1247 pub fn style_light_property(&self, property_name: &str) -> Result<Option<Vec<u8>>> {
1249 let map = self.inner.native()?;
1250 let property_name = maplibre_core::string::string_view(property_name);
1251 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1252 maplibre_core::check(unsafe {
1255 sys::mln_map_get_style_light_property(map, property_name.raw(), out.as_mut_ptr())
1256 })?;
1257 let Some(buffer) = out.into_option() else {
1258 return Ok(None);
1259 };
1260 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1262 }
1263
1264 pub fn set_style_transition_options(&self, options: &StyleTransitionOptions) -> Result<()> {
1268 let map = self.inner.native()?;
1269 let raw = maplibre_core::style::style_transition_options_to_native(options);
1270 maplibre_core::check(unsafe { sys::mln_map_set_style_transition_options(map, &raw) })
1273 }
1274
1275 pub fn style_transition_options(&self) -> Result<StyleTransitionOptions> {
1277 let map = self.inner.native()?;
1278 let mut raw = maplibre_core::style::empty_style_transition_options();
1279 maplibre_core::check(unsafe { sys::mln_map_get_style_transition_options(map, &mut raw) })?;
1281 Ok(maplibre_core::style::style_transition_options_from_native(
1282 &raw,
1283 ))
1284 }
1285
1286 pub fn set_layer_property(
1288 &self,
1289 layer_id: &str,
1290 property_name: &str,
1291 value: &[u8],
1292 ) -> Result<()> {
1293 let map = self.inner.native()?;
1294 let layer_id = maplibre_core::string::string_view(layer_id);
1295 let property_name = maplibre_core::string::string_view(property_name);
1296 let value = maplibre_core::string::buffer_view(value);
1297 maplibre_core::check(unsafe {
1300 sys::mln_map_set_layer_property(map, layer_id.raw(), property_name.raw(), value)
1301 })
1302 }
1303
1304 pub fn layer_property(&self, layer_id: &str, property_name: &str) -> Result<Option<Vec<u8>>> {
1306 let map = self.inner.native()?;
1307 let layer_id = maplibre_core::string::string_view(layer_id);
1308 let property_name = maplibre_core::string::string_view(property_name);
1309 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1310 maplibre_core::check(unsafe {
1313 sys::mln_map_get_layer_property(
1314 map,
1315 layer_id.raw(),
1316 property_name.raw(),
1317 out.as_mut_ptr(),
1318 )
1319 })?;
1320 let Some(buffer) = out.into_option() else {
1321 return Ok(None);
1322 };
1323 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1325 }
1326
1327 pub fn set_layer_filter(&self, layer_id: &str, filter: Option<&[u8]>) -> Result<()> {
1329 let map = self.inner.native()?;
1330 let layer_id = maplibre_core::string::string_view(layer_id);
1331 let native_filter = filter.map(maplibre_core::string::buffer_view);
1332 maplibre_core::check(unsafe {
1335 sys::mln_map_set_layer_filter(
1336 map,
1337 layer_id.raw(),
1338 native_filter.as_ref().map_or(ptr::null(), ptr::from_ref),
1339 )
1340 })
1341 }
1342
1343 pub fn layer_filter(&self, layer_id: &str) -> Result<Option<Vec<u8>>> {
1345 let map = self.inner.native()?;
1346 let layer_id = maplibre_core::string::string_view(layer_id);
1347 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1348 maplibre_core::check(unsafe {
1351 sys::mln_map_get_layer_filter(map, layer_id.raw(), out.as_mut_ptr())
1352 })?;
1353 let Some(buffer) = out.into_option() else {
1354 return Ok(None);
1355 };
1356 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1358 }
1359
1360 pub fn style_image_stretches(
1364 &self,
1365 image_id: &str,
1366 ) -> Result<Option<(Vec<ImageStretch>, Vec<ImageStretch>)>> {
1367 let map = self.inner.native()?;
1368 let image_id = maplibre_core::string::string_view(image_id);
1369 let mut x_count = 0;
1370 let mut y_count = 0;
1371 let mut found = false;
1372 maplibre_core::check(unsafe {
1376 sys::mln_map_copy_style_image_stretches(
1377 map,
1378 image_id.raw(),
1379 ptr::null_mut(),
1380 0,
1381 &mut x_count,
1382 ptr::null_mut(),
1383 0,
1384 &mut y_count,
1385 &mut found,
1386 )
1387 })?;
1388 if !found {
1389 return Ok(None);
1390 }
1391
1392 let mut stretch_x = vec![sys::mln_image_stretch { from: 0.0, to: 0.0 }; x_count];
1393 let mut stretch_y = vec![sys::mln_image_stretch { from: 0.0, to: 0.0 }; y_count];
1394 maplibre_core::check(unsafe {
1397 sys::mln_map_copy_style_image_stretches(
1398 map,
1399 image_id.raw(),
1400 stretch_x.as_mut_ptr(),
1401 stretch_x.len(),
1402 &mut x_count,
1403 stretch_y.as_mut_ptr(),
1404 stretch_y.len(),
1405 &mut y_count,
1406 &mut found,
1407 )
1408 })?;
1409 let to_public = |stretches: &[sys::mln_image_stretch]| -> Vec<ImageStretch> {
1410 stretches
1411 .iter()
1412 .map(|stretch| ImageStretch::new(stretch.from, stretch.to))
1413 .collect()
1414 };
1415 Ok(Some((to_public(&stretch_x), to_public(&stretch_y))))
1416 }
1417
1418 pub fn set_layer_source_layer(&self, layer_id: &str, source_layer: &str) -> Result<()> {
1422 let map = self.inner.native()?;
1423 let layer_id = maplibre_core::string::string_view(layer_id);
1424 let source_layer = maplibre_core::string::string_view(source_layer);
1425 maplibre_core::check(unsafe {
1427 sys::mln_map_set_layer_source_layer(map, layer_id.raw(), source_layer.raw())
1428 })
1429 }
1430
1431 pub fn layer_source_layer(&self, layer_id: &str) -> Result<String> {
1433 let map = self.inner.native()?;
1434 let layer_id = maplibre_core::string::string_view(layer_id);
1435 unsafe {
1438 copy_text(|text, capacity, out_size| {
1439 sys::mln_map_copy_layer_source_layer(map, layer_id.raw(), text, capacity, out_size)
1440 })
1441 }
1442 }
1443
1444 pub fn set_layer_source_id(&self, layer_id: &str, source_id: &str) -> Result<()> {
1449 let map = self.inner.native()?;
1450 let layer_id = maplibre_core::string::string_view(layer_id);
1451 let source_id = maplibre_core::string::string_view(source_id);
1452 maplibre_core::check(unsafe {
1454 sys::mln_map_set_layer_source_id(map, layer_id.raw(), source_id.raw())
1455 })
1456 }
1457
1458 pub fn layer_source_id(&self, layer_id: &str) -> Result<String> {
1460 let map = self.inner.native()?;
1461 let layer_id = maplibre_core::string::string_view(layer_id);
1462 unsafe {
1465 copy_text(|text, capacity, out_size| {
1466 sys::mln_map_copy_layer_source_id(map, layer_id.raw(), text, capacity, out_size)
1467 })
1468 }
1469 }
1470
1471 pub fn set_layer_min_zoom(&self, layer_id: &str, min_zoom: f64) -> Result<()> {
1475 let map = self.inner.native()?;
1476 let layer_id = maplibre_core::string::string_view(layer_id);
1477 maplibre_core::check(unsafe {
1479 sys::mln_map_set_layer_min_zoom(map, layer_id.raw(), min_zoom)
1480 })
1481 }
1482
1483 pub fn layer_min_zoom(&self, layer_id: &str) -> Result<f64> {
1487 let map = self.inner.native()?;
1488 let layer_id = maplibre_core::string::string_view(layer_id);
1489 let mut min_zoom = 0.0;
1490 maplibre_core::check(unsafe {
1493 sys::mln_map_get_layer_min_zoom(map, layer_id.raw(), &mut min_zoom)
1494 })?;
1495 Ok(min_zoom)
1496 }
1497
1498 pub fn set_layer_max_zoom(&self, layer_id: &str, max_zoom: f64) -> Result<()> {
1502 let map = self.inner.native()?;
1503 let layer_id = maplibre_core::string::string_view(layer_id);
1504 maplibre_core::check(unsafe {
1506 sys::mln_map_set_layer_max_zoom(map, layer_id.raw(), max_zoom)
1507 })
1508 }
1509
1510 pub fn layer_max_zoom(&self, layer_id: &str) -> Result<f64> {
1514 let map = self.inner.native()?;
1515 let layer_id = maplibre_core::string::string_view(layer_id);
1516 let mut max_zoom = 0.0;
1517 maplibre_core::check(unsafe {
1520 sys::mln_map_get_layer_max_zoom(map, layer_id.raw(), &mut max_zoom)
1521 })?;
1522 Ok(max_zoom)
1523 }
1524
1525 pub fn set_layer_visibility(
1527 &self,
1528 layer_id: &str,
1529 visibility: StyleLayerVisibility,
1530 ) -> Result<()> {
1531 let map = self.inner.native()?;
1532 let layer_id = maplibre_core::string::string_view(layer_id);
1533 maplibre_core::check(unsafe {
1535 sys::mln_map_set_layer_visibility(map, layer_id.raw(), visibility.raw_value())
1536 })
1537 }
1538
1539 pub fn layer_visibility(&self, layer_id: &str) -> Result<StyleLayerVisibility> {
1541 let map = self.inner.native()?;
1542 let layer_id = maplibre_core::string::string_view(layer_id);
1543 let mut visibility = 0;
1544 maplibre_core::check(unsafe {
1547 sys::mln_map_get_layer_visibility(map, layer_id.raw(), &mut visibility)
1548 })?;
1549 Ok(StyleLayerVisibility::from_raw(visibility))
1550 }
1551
1552 pub fn style_source_ids(&self) -> Result<Vec<String>> {
1554 let map = self.inner.native()?;
1555 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_id_list>::new();
1556 maplibre_core::check(unsafe { sys::mln_map_list_style_source_ids(map, out.as_mut_ptr()) })?;
1560 unsafe { maplibre_core::style::copy_style_id_list(out.into_live("mln_style_id_list")?) }
1563 }
1564
1565 pub fn style_layer_ids(&self) -> Result<Vec<String>> {
1567 let map = self.inner.native()?;
1568 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_id_list>::new();
1569 maplibre_core::check(unsafe { sys::mln_map_list_style_layer_ids(map, out.as_mut_ptr()) })?;
1573 unsafe { maplibre_core::style::copy_style_id_list(out.into_live("mln_style_id_list")?) }
1576 }
1577}
1578
1579unsafe fn copy_text(
1587 copy: impl Fn(*mut std::os::raw::c_char, usize, *mut usize) -> sys::mln_status,
1588) -> Result<String> {
1589 let mut required = 0;
1590 maplibre_core::check(copy(ptr::null_mut(), 0, &mut required))?;
1591 if required == 0 {
1592 return Ok(String::new());
1593 }
1594
1595 let mut buffer = vec![0u8; required];
1596 let mut copied = 0;
1597 maplibre_core::check(copy(buffer.as_mut_ptr().cast(), buffer.len(), &mut copied))?;
1598 if copied > buffer.len() {
1599 return Err(Error::new(
1600 ErrorKind::NativeError,
1601 None,
1602 "native text size exceeded caller buffer",
1603 ));
1604 }
1605 buffer.truncate(copied);
1606 String::from_utf8(buffer).map_err(|_| {
1607 Error::new(
1608 ErrorKind::NativeError,
1609 None,
1610 "native text was not valid UTF-8",
1611 )
1612 })
1613}
1614
1615unsafe fn copy_bytes(
1622 copy: impl Fn(*mut u8, usize, *mut usize) -> sys::mln_status,
1623) -> Result<Vec<u8>> {
1624 let mut required = 0;
1625 maplibre_core::check(copy(ptr::null_mut(), 0, &mut required))?;
1626 if required == 0 {
1627 return Ok(Vec::new());
1628 }
1629
1630 let mut buffer = vec![0u8; required];
1631 let mut copied = 0;
1632 maplibre_core::check(copy(buffer.as_mut_ptr(), buffer.len(), &mut copied))?;
1633 if copied > buffer.len() {
1634 return Err(Error::new(
1635 ErrorKind::NativeError,
1636 None,
1637 "native byte size exceeded caller buffer",
1638 ));
1639 }
1640 buffer.truncate(copied);
1641 Ok(buffer)
1642}