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::values::lat_lngs_to_native;
17use maplibre_native_ffi_sys as sys;
18
19use crate::custom_geometry::{CanonicalTileId, CustomGeometrySourceState};
20use crate::render::PremultipliedRgba8Image;
21use crate::values::NativeValue;
22use crate::{CustomGeometrySourceOptions, Error, ErrorKind, LatLng, LatLngBounds, Result};
23
24impl super::MapHandle {
25 pub fn set_style_url(&self, url: &str) -> Result<()> {
31 let map = self.inner.native()?;
32 let url = maplibre_core::string::c_string(url)?;
33 maplibre_core::check(unsafe { sys::mln_map_set_style_url(map, url.as_ptr()) })?;
36 Ok(())
37 }
38
39 pub fn set_style_json(&self, json: &[u8]) -> Result<()> {
44 let map = self.inner.native()?;
45 let json = maplibre_core::string::buffer_view(json);
46 maplibre_core::check(unsafe { sys::mln_map_set_style_json(map, json) })
50 }
51
52 pub fn loaded_style_json(&self) -> Result<Vec<u8>> {
57 let map = self.inner.native()?;
58 unsafe {
61 copy_bytes(|text, capacity, out_size| {
62 sys::mln_map_copy_loaded_style_json(map, text, capacity, out_size)
63 })
64 }
65 }
66
67 pub fn style_url(&self) -> Result<String> {
74 let map = self.inner.native()?;
75 unsafe {
78 copy_text(|url, capacity, out_size| {
79 sys::mln_map_copy_style_url(map, url, capacity, out_size)
80 })
81 }
82 }
83
84 pub fn add_custom_geometry_source(
92 &self,
93 source_id: &str,
94 options: CustomGeometrySourceOptions,
95 ) -> Result<()> {
96 let map = self.inner.native()?;
97 let source_id_view = maplibre_core::string::string_view(source_id);
98 let state = CustomGeometrySourceState::new(options);
99 let descriptor = state.descriptor();
100 let state = Box::into_raw(state);
103 let status = unsafe {
106 sys::mln_map_add_custom_geometry_source(map, source_id_view.raw(), &descriptor)
107 };
108 if let Err(error) = maplibre_core::check(status) {
109 drop(unsafe { Box::from_raw(state) });
112 return Err(error);
113 }
114 Ok(())
115 }
116
117 pub fn set_custom_geometry_source_tile_data(
119 &self,
120 source_id: &str,
121 tile_id: CanonicalTileId,
122 data: &[u8],
123 ) -> Result<()> {
124 let map = self.inner.native()?;
125 let source_id = maplibre_core::string::string_view(source_id);
126 let data = maplibre_core::string::buffer_view(data);
127 maplibre_core::check(unsafe {
130 sys::mln_map_set_custom_geometry_source_tile_data(
131 map,
132 source_id.raw(),
133 tile_id.to_native(),
134 data,
135 )
136 })
137 }
138
139 pub fn invalidate_custom_geometry_source_tile(
141 &self,
142 source_id: &str,
143 tile_id: CanonicalTileId,
144 ) -> Result<()> {
145 let map = self.inner.native()?;
146 let source_id = maplibre_core::string::string_view(source_id);
147 maplibre_core::check(unsafe {
150 sys::mln_map_invalidate_custom_geometry_source_tile(
151 map,
152 source_id.raw(),
153 tile_id.to_native(),
154 )
155 })
156 }
157
158 pub fn invalidate_custom_geometry_source_region(
160 &self,
161 source_id: &str,
162 bounds: LatLngBounds,
163 ) -> Result<()> {
164 let map = self.inner.native()?;
165 let source_id = maplibre_core::string::string_view(source_id);
166 maplibre_core::check(unsafe {
169 sys::mln_map_invalidate_custom_geometry_source_region(
170 map,
171 source_id.raw(),
172 bounds.to_native(),
173 )
174 })
175 }
176
177 pub fn add_style_source_json(&self, source_id: &str, source_json: &[u8]) -> Result<()> {
179 let map = self.inner.native()?;
180 let source_id = maplibre_core::string::string_view(source_id);
181 let source_json = maplibre_core::string::buffer_view(source_json);
182 maplibre_core::check(unsafe {
185 sys::mln_map_add_style_source_json(map, source_id.raw(), source_json)
186 })
187 }
188
189 pub fn add_vector_source_url(
191 &self,
192 source_id: &str,
193 url: &str,
194 options: Option<&TileSourceOptions>,
195 ) -> Result<()> {
196 let map = self.inner.native()?;
197 let source_id = maplibre_core::string::string_view(source_id);
198 let url = maplibre_core::string::string_view(url);
199 let options = options.map(TileSourceOptions::to_native);
200 let options_ptr = options
201 .as_ref()
202 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
203 maplibre_core::check(unsafe {
206 sys::mln_map_add_vector_source_url(map, source_id.raw(), url.raw(), options_ptr)
207 })
208 }
209
210 pub fn add_vector_source_tiles<S: AsRef<str>>(
212 &self,
213 source_id: &str,
214 tiles: &[S],
215 options: Option<&TileSourceOptions>,
216 ) -> Result<()> {
217 let map = self.inner.native()?;
218 let source_id = maplibre_core::string::string_view(source_id);
219 let raw_tiles = NativeTileUrls::new(tiles);
220 let options = options.map(TileSourceOptions::to_native);
221 let options_ptr = options
222 .as_ref()
223 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
224 maplibre_core::check(unsafe {
228 sys::mln_map_add_vector_source_tiles(
229 map,
230 source_id.raw(),
231 raw_tiles.as_ptr(),
232 raw_tiles.len(),
233 options_ptr,
234 )
235 })
236 }
237
238 pub fn add_raster_source_url(
240 &self,
241 source_id: &str,
242 url: &str,
243 options: Option<&TileSourceOptions>,
244 ) -> Result<()> {
245 let map = self.inner.native()?;
246 let source_id = maplibre_core::string::string_view(source_id);
247 let url = maplibre_core::string::string_view(url);
248 let options = options.map(TileSourceOptions::to_native);
249 let options_ptr = options
250 .as_ref()
251 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
252 maplibre_core::check(unsafe {
255 sys::mln_map_add_raster_source_url(map, source_id.raw(), url.raw(), options_ptr)
256 })
257 }
258
259 pub fn add_raster_source_tiles<S: AsRef<str>>(
261 &self,
262 source_id: &str,
263 tiles: &[S],
264 options: Option<&TileSourceOptions>,
265 ) -> Result<()> {
266 let map = self.inner.native()?;
267 let source_id = maplibre_core::string::string_view(source_id);
268 let raw_tiles = NativeTileUrls::new(tiles);
269 let options = options.map(TileSourceOptions::to_native);
270 let options_ptr = options
271 .as_ref()
272 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
273 maplibre_core::check(unsafe {
277 sys::mln_map_add_raster_source_tiles(
278 map,
279 source_id.raw(),
280 raw_tiles.as_ptr(),
281 raw_tiles.len(),
282 options_ptr,
283 )
284 })
285 }
286
287 pub fn add_raster_dem_source_url(
289 &self,
290 source_id: &str,
291 url: &str,
292 options: Option<&TileSourceOptions>,
293 ) -> Result<()> {
294 let map = self.inner.native()?;
295 let source_id = maplibre_core::string::string_view(source_id);
296 let url = maplibre_core::string::string_view(url);
297 let options = options.map(TileSourceOptions::to_native);
298 let options_ptr = options
299 .as_ref()
300 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
301 maplibre_core::check(unsafe {
304 sys::mln_map_add_raster_dem_source_url(map, source_id.raw(), url.raw(), options_ptr)
305 })
306 }
307
308 pub fn add_raster_dem_source_tiles<S: AsRef<str>>(
310 &self,
311 source_id: &str,
312 tiles: &[S],
313 options: Option<&TileSourceOptions>,
314 ) -> Result<()> {
315 let map = self.inner.native()?;
316 let source_id = maplibre_core::string::string_view(source_id);
317 let raw_tiles = NativeTileUrls::new(tiles);
318 let options = options.map(TileSourceOptions::to_native);
319 let options_ptr = options
320 .as_ref()
321 .map_or(ptr::null(), NativeTileSourceOptions::as_ptr);
322 maplibre_core::check(unsafe {
326 sys::mln_map_add_raster_dem_source_tiles(
327 map,
328 source_id.raw(),
329 raw_tiles.as_ptr(),
330 raw_tiles.len(),
331 options_ptr,
332 )
333 })
334 }
335
336 pub fn add_image_source_url(
342 &self,
343 source_id: &str,
344 coordinates: &[LatLng; 4],
345 url: &str,
346 ) -> Result<()> {
347 let map = self.inner.native()?;
348 let source_id = maplibre_core::string::string_view(source_id);
349 let coordinates = lat_lngs_to_native(coordinates);
350 let url = maplibre_core::string::string_view(url);
351 maplibre_core::check(unsafe {
355 sys::mln_map_add_image_source_url(
356 map,
357 source_id.raw(),
358 const_ptr_or_null(&coordinates),
359 coordinates.len(),
360 url.raw(),
361 )
362 })
363 }
364
365 pub fn add_image_source_image(
371 &self,
372 source_id: &str,
373 coordinates: &[LatLng; 4],
374 image: &PremultipliedRgba8Image,
375 ) -> Result<()> {
376 let map = self.inner.native()?;
377 let source_id = maplibre_core::string::string_view(source_id);
378 let coordinates = lat_lngs_to_native(coordinates);
379 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
380 maplibre_core::check(unsafe {
384 sys::mln_map_add_image_source_image(
385 map,
386 source_id.raw(),
387 const_ptr_or_null(&coordinates),
388 coordinates.len(),
389 &image,
390 )
391 })
392 }
393
394 pub fn set_image_source_url(&self, source_id: &str, url: &str) -> Result<()> {
396 let map = self.inner.native()?;
397 let source_id = maplibre_core::string::string_view(source_id);
398 let url = maplibre_core::string::string_view(url);
399 maplibre_core::check(unsafe {
402 sys::mln_map_set_image_source_url(map, source_id.raw(), url.raw())
403 })
404 }
405
406 pub fn set_image_source_image(
408 &self,
409 source_id: &str,
410 image: &PremultipliedRgba8Image,
411 ) -> Result<()> {
412 let map = self.inner.native()?;
413 let source_id = maplibre_core::string::string_view(source_id);
414 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
415 maplibre_core::check(unsafe {
418 sys::mln_map_set_image_source_image(map, source_id.raw(), &image)
419 })
420 }
421
422 pub fn set_image_source_coordinates(
428 &self,
429 source_id: &str,
430 coordinates: &[LatLng; 4],
431 ) -> Result<()> {
432 let map = self.inner.native()?;
433 let source_id = maplibre_core::string::string_view(source_id);
434 let coordinates = lat_lngs_to_native(coordinates);
435 maplibre_core::check(unsafe {
439 sys::mln_map_set_image_source_coordinates(
440 map,
441 source_id.raw(),
442 const_ptr_or_null(&coordinates),
443 coordinates.len(),
444 )
445 })
446 }
447
448 pub fn image_source_coordinates(&self, source_id: &str) -> Result<Option<[LatLng; 4]>> {
450 let map = self.inner.native()?;
451 let source_id = maplibre_core::string::string_view(source_id);
452 let mut coordinates = [sys::mln_lat_lng {
453 latitude: 0.0,
454 longitude: 0.0,
455 }; 4];
456 let mut coordinate_count = 0;
457 let mut found = false;
458 maplibre_core::check(unsafe {
462 sys::mln_map_get_image_source_coordinates(
463 map,
464 source_id.raw(),
465 coordinates.as_mut_ptr(),
466 coordinates.len(),
467 &mut coordinate_count,
468 &mut found,
469 )
470 })?;
471 if !found {
472 return Ok(None);
473 }
474 if coordinate_count != coordinates.len() {
475 return Err(Error::new(
476 ErrorKind::NativeError,
477 None,
478 "native image source coordinate count did not match Rust image source invariant",
479 ));
480 }
481 Ok(Some(coordinates.map(LatLng::from_native)))
482 }
483
484 pub fn remove_style_source(&self, source_id: &str) -> Result<bool> {
489 let map = self.inner.native()?;
490 let source_id = maplibre_core::string::string_view(source_id);
491 let mut removed = false;
492 maplibre_core::check(unsafe {
495 sys::mln_map_remove_style_source(map, source_id.raw(), &mut removed)
496 })?;
497 Ok(removed)
498 }
499
500 pub fn style_source_exists(&self, source_id: &str) -> Result<bool> {
502 let map = self.inner.native()?;
503 let source_id = maplibre_core::string::string_view(source_id);
504 let mut exists = false;
505 maplibre_core::check(unsafe {
508 sys::mln_map_style_source_exists(map, source_id.raw(), &mut exists)
509 })?;
510 Ok(exists)
511 }
512
513 pub fn set_style_image(
515 &self,
516 image_id: &str,
517 image: &PremultipliedRgba8Image,
518 options: Option<&StyleImageOptions>,
519 ) -> Result<()> {
520 let map = self.inner.native()?;
521 let image_id = maplibre_core::string::string_view(image_id);
522 let image = maplibre_core::values::premultiplied_rgba8_image_to_native(image);
523 let options = options.map(StyleImageOptions::to_native);
524 let options_ptr = options
525 .as_ref()
526 .map_or(ptr::null(), NativeStyleImageOptions::as_ptr);
527 maplibre_core::check(unsafe {
531 sys::mln_map_set_style_image(map, image_id.raw(), &image, options_ptr)
532 })
533 }
534
535 pub fn remove_style_image(&self, image_id: &str) -> Result<bool> {
539 let map = self.inner.native()?;
540 let image_id = maplibre_core::string::string_view(image_id);
541 let mut removed = false;
542 maplibre_core::check(unsafe {
545 sys::mln_map_remove_style_image(map, image_id.raw(), &mut removed)
546 })?;
547 Ok(removed)
548 }
549
550 pub fn style_image_exists(&self, image_id: &str) -> Result<bool> {
552 let map = self.inner.native()?;
553 let image_id = maplibre_core::string::string_view(image_id);
554 let mut exists = false;
555 maplibre_core::check(unsafe {
558 sys::mln_map_style_image_exists(map, image_id.raw(), &mut exists)
559 })?;
560 Ok(exists)
561 }
562
563 pub fn style_image_info(&self, image_id: &str) -> Result<Option<StyleImageInfo>> {
565 let map = self.inner.native()?;
566 let image_id = maplibre_core::string::string_view(image_id);
567 let mut info = maplibre_core::style::empty_style_image_info();
568 let mut found = false;
569 maplibre_core::check(unsafe {
573 sys::mln_map_get_style_image_info(map, image_id.raw(), &mut info, &mut found)
574 })?;
575 Ok(found.then(|| maplibre_core::values::style_image_info_from_native(&info)))
576 }
577
578 pub fn copy_style_image_premultiplied_rgba8(
580 &self,
581 image_id: &str,
582 ) -> Result<Option<StyleImage>> {
583 let map = self.inner.native()?;
584 let image_id = maplibre_core::string::string_view(image_id);
585 let mut raw_info = maplibre_core::style::empty_style_image_info();
586 let mut info_found = false;
587 maplibre_core::check(unsafe {
591 sys::mln_map_get_style_image_info(map, image_id.raw(), &mut raw_info, &mut info_found)
592 })?;
593 if !info_found {
594 return Ok(None);
595 }
596 let info = maplibre_core::values::style_image_info_from_native(&raw_info);
597
598 let mut data = vec![0u8; info.byte_length];
599 let mut copied_size = 0;
600 let mut found = false;
601 let pixels = if data.is_empty() {
602 ptr::null_mut()
603 } else {
604 data.as_mut_ptr()
605 };
606 maplibre_core::check(unsafe {
610 sys::mln_map_copy_style_image_premultiplied_rgba8(
611 map,
612 image_id.raw(),
613 pixels,
614 data.len(),
615 &mut copied_size,
616 &mut found,
617 )
618 })?;
619 if !found {
620 return Ok(None);
621 }
622 maplibre_core::style::style_image_from_copied_premultiplied_rgba8(info, data, copied_size)
623 .map(Some)
624 }
625
626 pub fn style_source_type(&self, source_id: &str) -> Result<Option<SourceType>> {
628 let map = self.inner.native()?;
629 let source_id = maplibre_core::string::string_view(source_id);
630 let mut raw_source_type = sys::MLN_STYLE_SOURCE_TYPE_UNKNOWN;
631 let mut found = false;
632 maplibre_core::check(unsafe {
635 sys::mln_map_get_style_source_type(
636 map,
637 source_id.raw(),
638 &mut raw_source_type,
639 &mut found,
640 )
641 })?;
642 Ok(found.then(|| SourceType::from_raw(raw_source_type)))
643 }
644
645 pub fn style_source_info(&self, source_id: &str) -> Result<Option<SourceInfo>> {
647 let map = self.inner.native()?;
648 let source_id = maplibre_core::string::string_view(source_id);
649 let mut info = maplibre_core::style::empty_style_source_info();
650 let mut found = false;
651 maplibre_core::check(unsafe {
655 sys::mln_map_get_style_source_info(map, source_id.raw(), &mut info, &mut found)
656 })?;
657 if !found {
658 return Ok(None);
659 }
660
661 let attribution = if info.has_attribution {
662 match self.copy_style_source_attribution(map, source_id.raw(), info.attribution_size)? {
663 Some(attribution) => Some(attribution),
664 None => return Ok(None),
665 }
666 } else {
667 None
668 };
669
670 let url = if info.fields & sys::MLN_STYLE_SOURCE_INFO_URL != 0 {
671 match self.copy_style_source_url(map, source_id.raw(), info.url_size)? {
672 Some(url) => Some(url),
673 None => return Ok(None),
674 }
675 } else {
676 None
677 };
678
679 let tiles = if info.fields & sys::MLN_STYLE_SOURCE_INFO_TILEJSON != 0 {
680 match self.copy_style_source_tile_urls(map, source_id.raw())? {
681 Some(tiles) => tiles,
682 None => return Ok(None),
683 }
684 } else {
685 Vec::new()
686 };
687
688 Ok(Some(maplibre_core::style::style_source_info_from_native(
689 &info,
690 attribution,
691 url,
692 tiles,
693 )))
694 }
695
696 fn copy_style_source_attribution(
697 &self,
698 map: sys::mln_map,
699 source_id: sys::mln_buffer_view,
700 attribution_size: usize,
701 ) -> Result<Option<String>> {
702 if attribution_size == 0 {
703 let mut copied_size = 0;
704 let mut found = false;
705 maplibre_core::check(unsafe {
709 sys::mln_map_copy_style_source_attribution(
710 map,
711 source_id,
712 ptr::null_mut(),
713 0,
714 &mut copied_size,
715 &mut found,
716 )
717 })?;
718 return Ok(found.then(String::new));
719 }
720
721 let mut buffer = vec![0u8; attribution_size];
722 let mut copied_size = 0;
723 let mut found = false;
724 maplibre_core::check(unsafe {
728 sys::mln_map_copy_style_source_attribution(
729 map,
730 source_id,
731 buffer.as_mut_ptr().cast(),
732 buffer.len(),
733 &mut copied_size,
734 &mut found,
735 )
736 })?;
737 if !found {
738 return Ok(None);
739 }
740 if copied_size > buffer.len() {
741 return Err(Error::new(
742 ErrorKind::NativeError,
743 None,
744 "native style source attribution size exceeded caller buffer",
745 ));
746 }
747 buffer.truncate(copied_size);
748 String::from_utf8(buffer).map(Some).map_err(|error| {
749 Error::invalid_argument(format!(
750 "native style source attribution was not valid UTF-8: {error}"
751 ))
752 })
753 }
754
755 fn copy_style_source_url(
756 &self,
757 map: sys::mln_map,
758 source_id: sys::mln_buffer_view,
759 url_size: usize,
760 ) -> Result<Option<String>> {
761 let mut buffer = vec![0u8; url_size];
762 let mut copied_size = 0;
763 let mut found = false;
764 maplibre_core::check(unsafe {
768 sys::mln_map_copy_style_source_url(
769 map,
770 source_id,
771 if buffer.is_empty() {
772 ptr::null_mut()
773 } else {
774 buffer.as_mut_ptr().cast()
775 },
776 buffer.len(),
777 &mut copied_size,
778 &mut found,
779 )
780 })?;
781 if !found {
782 return Ok(None);
783 }
784 if copied_size > buffer.len() {
785 return Err(Error::new(
786 ErrorKind::NativeError,
787 None,
788 "native style source URL size exceeded caller buffer",
789 ));
790 }
791 buffer.truncate(copied_size);
792 String::from_utf8(buffer).map(Some).map_err(|error| {
793 Error::invalid_argument(format!(
794 "native style source URL was not valid UTF-8: {error}"
795 ))
796 })
797 }
798
799 fn copy_style_source_tile_urls(
800 &self,
801 map: sys::mln_map,
802 source_id: sys::mln_buffer_view,
803 ) -> Result<Option<Vec<String>>> {
804 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_string_list>::new();
805 let mut found = false;
806 maplibre_core::check(unsafe {
809 sys::mln_map_get_style_source_tile_urls(map, source_id, out.as_mut_ptr(), &mut found)
810 })?;
811 if !found {
812 return Ok(None);
813 }
814 unsafe {
817 maplibre_core::style::copy_style_string_list(out.into_live("mln_style_string_list")?)
818 .map(Some)
819 }
820 }
821
822 pub fn add_geojson_source_url(
825 &self,
826 source_id: &str,
827 url: &str,
828 options: Option<&GeoJsonSourceOptions>,
829 ) -> Result<()> {
830 let map = self.inner.native()?;
831 let source_id = maplibre_core::string::string_view(source_id);
832 let url = maplibre_core::string::string_view(url);
833 let options = options
834 .map(GeoJsonSourceOptions::try_to_native)
835 .transpose()?;
836 let options_ptr = options
837 .as_ref()
838 .map_or(ptr::null(), NativeGeoJsonSourceOptions::as_ptr);
839 maplibre_core::check(unsafe {
843 sys::mln_map_add_geojson_source_url(map, source_id.raw(), url.raw(), options_ptr)
844 })
845 }
846
847 pub fn add_geojson_source_data(
852 &self,
853 source_id: &str,
854 data: &crate::GeoJsonSourceDataHandle,
855 ) -> Result<()> {
856 let map = self.inner.native()?;
857 let source_id = maplibre_core::string::string_view(source_id);
858 maplibre_core::check(unsafe {
861 sys::mln_map_add_geojson_source_data(map, source_id.raw(), data.native())
862 })
863 }
864
865 pub fn set_geojson_source_url(&self, source_id: &str, url: &str) -> Result<()> {
869 let map = self.inner.native()?;
870 let source_id = maplibre_core::string::string_view(source_id);
871 let url = maplibre_core::string::string_view(url);
872 maplibre_core::check(unsafe {
874 sys::mln_map_set_geojson_source_url(map, source_id.raw(), url.raw())
875 })
876 }
877
878 pub fn set_geojson_source_data(
885 &self,
886 source_id: &str,
887 data: &crate::GeoJsonSourceDataHandle,
888 ) -> Result<()> {
889 let map = self.inner.native()?;
890 let source_id = maplibre_core::string::string_view(source_id);
891 maplibre_core::check(unsafe {
894 sys::mln_map_set_geojson_source_data(map, source_id.raw(), data.native())
895 })
896 }
897
898 pub fn set_geojson_source_synchronous_tiling(
905 &self,
906 source_id: &str,
907 enabled: bool,
908 ) -> Result<()> {
909 let map = self.inner.native()?;
910 let source_id = maplibre_core::string::string_view(source_id);
911 maplibre_core::check(unsafe {
913 sys::mln_map_set_geojson_source_synchronous_tiling(map, source_id.raw(), enabled)
914 })
915 }
916
917 pub fn add_style_layer_json(
919 &self,
920 layer_json: &[u8],
921 before_layer_id: Option<&str>,
922 ) -> Result<()> {
923 let map = self.inner.native()?;
924 let layer_json = maplibre_core::string::buffer_view(layer_json);
925 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
926 maplibre_core::check(unsafe {
929 sys::mln_map_add_style_layer_json(map, layer_json, before_layer_id.raw())
930 })
931 }
932
933 pub fn add_hillshade_layer(
935 &self,
936 layer_id: &str,
937 source_id: &str,
938 before_layer_id: Option<&str>,
939 ) -> Result<()> {
940 let map = self.inner.native()?;
941 let layer_id = maplibre_core::string::string_view(layer_id);
942 let source_id = maplibre_core::string::string_view(source_id);
943 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
944 maplibre_core::check(unsafe {
946 sys::mln_map_add_hillshade_layer(
947 map,
948 layer_id.raw(),
949 source_id.raw(),
950 before_layer_id.raw(),
951 )
952 })
953 }
954
955 pub fn add_color_relief_layer(
957 &self,
958 layer_id: &str,
959 source_id: &str,
960 before_layer_id: Option<&str>,
961 ) -> Result<()> {
962 let map = self.inner.native()?;
963 let layer_id = maplibre_core::string::string_view(layer_id);
964 let source_id = maplibre_core::string::string_view(source_id);
965 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
966 maplibre_core::check(unsafe {
968 sys::mln_map_add_color_relief_layer(
969 map,
970 layer_id.raw(),
971 source_id.raw(),
972 before_layer_id.raw(),
973 )
974 })
975 }
976
977 pub fn add_location_indicator_layer(
979 &self,
980 layer_id: &str,
981 before_layer_id: Option<&str>,
982 ) -> Result<()> {
983 let map = self.inner.native()?;
984 let layer_id = maplibre_core::string::string_view(layer_id);
985 let before_layer_id = maplibre_core::string::string_view(before_layer_id.unwrap_or(""));
986 maplibre_core::check(unsafe {
988 sys::mln_map_add_location_indicator_layer(map, layer_id.raw(), before_layer_id.raw())
989 })
990 }
991
992 pub fn set_location_indicator_location(
994 &self,
995 layer_id: &str,
996 coordinate: LatLng,
997 altitude: f64,
998 ) -> Result<()> {
999 let map = self.inner.native()?;
1000 let layer_id = maplibre_core::string::string_view(layer_id);
1001 maplibre_core::check(unsafe {
1004 sys::mln_map_set_location_indicator_location(
1005 map,
1006 layer_id.raw(),
1007 coordinate.to_native(),
1008 altitude,
1009 )
1010 })
1011 }
1012
1013 pub fn set_location_indicator_bearing(&self, layer_id: &str, bearing: f64) -> Result<()> {
1015 let map = self.inner.native()?;
1016 let layer_id = maplibre_core::string::string_view(layer_id);
1017 maplibre_core::check(unsafe {
1019 sys::mln_map_set_location_indicator_bearing(map, layer_id.raw(), bearing)
1020 })
1021 }
1022
1023 pub fn set_location_indicator_accuracy_radius(
1025 &self,
1026 layer_id: &str,
1027 radius: f64,
1028 ) -> Result<()> {
1029 let map = self.inner.native()?;
1030 let layer_id = maplibre_core::string::string_view(layer_id);
1031 maplibre_core::check(unsafe {
1033 sys::mln_map_set_location_indicator_accuracy_radius(map, layer_id.raw(), radius)
1034 })
1035 }
1036
1037 pub fn set_location_indicator_image_name(
1039 &self,
1040 layer_id: &str,
1041 image_kind: LocationIndicatorImageKind,
1042 image_id: &str,
1043 ) -> Result<()> {
1044 let map = self.inner.native()?;
1045 let layer_id = maplibre_core::string::string_view(layer_id);
1046 let image_id = maplibre_core::string::string_view(image_id);
1047 maplibre_core::check(unsafe {
1050 sys::mln_map_set_location_indicator_image_name(
1051 map,
1052 layer_id.raw(),
1053 image_kind.raw_value(),
1054 image_id.raw(),
1055 )
1056 })
1057 }
1058
1059 pub fn style_layer_json(&self, layer_id: &str) -> Result<Option<Vec<u8>>> {
1061 let map = self.inner.native()?;
1062 let layer_id = maplibre_core::string::string_view(layer_id);
1063 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1064 let mut found = false;
1065 maplibre_core::check(unsafe {
1068 sys::mln_map_get_style_layer_json(map, layer_id.raw(), out.as_mut_ptr(), &mut found)
1069 })?;
1070 if !found {
1071 return Ok(None);
1072 }
1073 unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }.map(Some)
1075 }
1076
1077 pub fn set_style_light_json(&self, light_json: &[u8]) -> Result<()> {
1079 let map = self.inner.native()?;
1080 let light_json = maplibre_core::string::buffer_view(light_json);
1081 maplibre_core::check(unsafe { sys::mln_map_set_style_light_json(map, light_json) })
1083 }
1084
1085 pub fn set_style_light_property(&self, property_name: &str, value: &[u8]) -> Result<()> {
1087 let map = self.inner.native()?;
1088 let property_name = maplibre_core::string::string_view(property_name);
1089 let value = maplibre_core::string::buffer_view(value);
1090 maplibre_core::check(unsafe {
1092 sys::mln_map_set_style_light_property(map, property_name.raw(), value)
1093 })
1094 }
1095
1096 pub fn style_light_property(&self, property_name: &str) -> Result<Option<Vec<u8>>> {
1098 let map = self.inner.native()?;
1099 let property_name = maplibre_core::string::string_view(property_name);
1100 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1101 maplibre_core::check(unsafe {
1104 sys::mln_map_get_style_light_property(map, property_name.raw(), out.as_mut_ptr())
1105 })?;
1106 let Some(buffer) = out.into_option() else {
1107 return Ok(None);
1108 };
1109 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1111 }
1112
1113 pub fn set_style_transition_options(&self, options: &StyleTransitionOptions) -> Result<()> {
1117 let map = self.inner.native()?;
1118 let raw = maplibre_core::style::style_transition_options_to_native(options);
1119 maplibre_core::check(unsafe { sys::mln_map_set_style_transition_options(map, &raw) })
1122 }
1123
1124 pub fn style_transition_options(&self) -> Result<StyleTransitionOptions> {
1126 let map = self.inner.native()?;
1127 let mut raw = maplibre_core::style::empty_style_transition_options();
1128 maplibre_core::check(unsafe { sys::mln_map_get_style_transition_options(map, &mut raw) })?;
1130 Ok(maplibre_core::style::style_transition_options_from_native(
1131 &raw,
1132 ))
1133 }
1134
1135 pub fn set_layer_property(
1137 &self,
1138 layer_id: &str,
1139 property_name: &str,
1140 value: &[u8],
1141 ) -> Result<()> {
1142 let map = self.inner.native()?;
1143 let layer_id = maplibre_core::string::string_view(layer_id);
1144 let property_name = maplibre_core::string::string_view(property_name);
1145 let value = maplibre_core::string::buffer_view(value);
1146 maplibre_core::check(unsafe {
1149 sys::mln_map_set_layer_property(map, layer_id.raw(), property_name.raw(), value)
1150 })
1151 }
1152
1153 pub fn layer_property(&self, layer_id: &str, property_name: &str) -> Result<Option<Vec<u8>>> {
1155 let map = self.inner.native()?;
1156 let layer_id = maplibre_core::string::string_view(layer_id);
1157 let property_name = maplibre_core::string::string_view(property_name);
1158 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1159 maplibre_core::check(unsafe {
1162 sys::mln_map_get_layer_property(
1163 map,
1164 layer_id.raw(),
1165 property_name.raw(),
1166 out.as_mut_ptr(),
1167 )
1168 })?;
1169 let Some(buffer) = out.into_option() else {
1170 return Ok(None);
1171 };
1172 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1174 }
1175
1176 pub fn set_layer_filter(&self, layer_id: &str, filter: Option<&[u8]>) -> Result<()> {
1178 let map = self.inner.native()?;
1179 let layer_id = maplibre_core::string::string_view(layer_id);
1180 let native_filter = filter.map(maplibre_core::string::buffer_view);
1181 maplibre_core::check(unsafe {
1184 sys::mln_map_set_layer_filter(
1185 map,
1186 layer_id.raw(),
1187 native_filter.as_ref().map_or(ptr::null(), ptr::from_ref),
1188 )
1189 })
1190 }
1191
1192 pub fn layer_filter(&self, layer_id: &str) -> Result<Option<Vec<u8>>> {
1194 let map = self.inner.native()?;
1195 let layer_id = maplibre_core::string::string_view(layer_id);
1196 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
1197 maplibre_core::check(unsafe {
1200 sys::mln_map_get_layer_filter(map, layer_id.raw(), out.as_mut_ptr())
1201 })?;
1202 let Some(buffer) = out.into_option() else {
1203 return Ok(None);
1204 };
1205 unsafe { maplibre_core::string::copy_owned_buffer(buffer) }.map(Some)
1207 }
1208
1209 pub fn style_image_stretches(
1213 &self,
1214 image_id: &str,
1215 ) -> Result<Option<(Vec<ImageStretch>, Vec<ImageStretch>)>> {
1216 let map = self.inner.native()?;
1217 let image_id = maplibre_core::string::string_view(image_id);
1218 let mut x_count = 0;
1219 let mut y_count = 0;
1220 let mut found = false;
1221 maplibre_core::check(unsafe {
1225 sys::mln_map_copy_style_image_stretches(
1226 map,
1227 image_id.raw(),
1228 ptr::null_mut(),
1229 0,
1230 &mut x_count,
1231 ptr::null_mut(),
1232 0,
1233 &mut y_count,
1234 &mut found,
1235 )
1236 })?;
1237 if !found {
1238 return Ok(None);
1239 }
1240
1241 let mut stretch_x = vec![sys::mln_image_stretch { from: 0.0, to: 0.0 }; x_count];
1242 let mut stretch_y = vec![sys::mln_image_stretch { from: 0.0, to: 0.0 }; y_count];
1243 maplibre_core::check(unsafe {
1246 sys::mln_map_copy_style_image_stretches(
1247 map,
1248 image_id.raw(),
1249 stretch_x.as_mut_ptr(),
1250 stretch_x.len(),
1251 &mut x_count,
1252 stretch_y.as_mut_ptr(),
1253 stretch_y.len(),
1254 &mut y_count,
1255 &mut found,
1256 )
1257 })?;
1258 let to_public = |stretches: &[sys::mln_image_stretch]| -> Vec<ImageStretch> {
1259 stretches
1260 .iter()
1261 .map(|stretch| ImageStretch::new(stretch.from, stretch.to))
1262 .collect()
1263 };
1264 Ok(Some((to_public(&stretch_x), to_public(&stretch_y))))
1265 }
1266
1267 pub fn set_layer_source_layer(&self, layer_id: &str, source_layer: &str) -> Result<()> {
1271 let map = self.inner.native()?;
1272 let layer_id = maplibre_core::string::string_view(layer_id);
1273 let source_layer = maplibre_core::string::string_view(source_layer);
1274 maplibre_core::check(unsafe {
1276 sys::mln_map_set_layer_source_layer(map, layer_id.raw(), source_layer.raw())
1277 })
1278 }
1279
1280 pub fn layer_source_layer(&self, layer_id: &str) -> Result<String> {
1282 let map = self.inner.native()?;
1283 let layer_id = maplibre_core::string::string_view(layer_id);
1284 unsafe {
1287 copy_text(|text, capacity, out_size| {
1288 sys::mln_map_copy_layer_source_layer(map, layer_id.raw(), text, capacity, out_size)
1289 })
1290 }
1291 }
1292
1293 pub fn set_layer_source_id(&self, layer_id: &str, source_id: &str) -> Result<()> {
1298 let map = self.inner.native()?;
1299 let layer_id = maplibre_core::string::string_view(layer_id);
1300 let source_id = maplibre_core::string::string_view(source_id);
1301 maplibre_core::check(unsafe {
1303 sys::mln_map_set_layer_source_id(map, layer_id.raw(), source_id.raw())
1304 })
1305 }
1306
1307 pub fn layer_source_id(&self, layer_id: &str) -> Result<String> {
1309 let map = self.inner.native()?;
1310 let layer_id = maplibre_core::string::string_view(layer_id);
1311 unsafe {
1314 copy_text(|text, capacity, out_size| {
1315 sys::mln_map_copy_layer_source_id(map, layer_id.raw(), text, capacity, out_size)
1316 })
1317 }
1318 }
1319
1320 pub fn set_layer_min_zoom(&self, layer_id: &str, min_zoom: f64) -> Result<()> {
1324 let map = self.inner.native()?;
1325 let layer_id = maplibre_core::string::string_view(layer_id);
1326 maplibre_core::check(unsafe {
1328 sys::mln_map_set_layer_min_zoom(map, layer_id.raw(), min_zoom)
1329 })
1330 }
1331
1332 pub fn layer_min_zoom(&self, layer_id: &str) -> Result<f64> {
1336 let map = self.inner.native()?;
1337 let layer_id = maplibre_core::string::string_view(layer_id);
1338 let mut min_zoom = 0.0;
1339 maplibre_core::check(unsafe {
1342 sys::mln_map_get_layer_min_zoom(map, layer_id.raw(), &mut min_zoom)
1343 })?;
1344 Ok(min_zoom)
1345 }
1346
1347 pub fn set_layer_max_zoom(&self, layer_id: &str, max_zoom: f64) -> Result<()> {
1351 let map = self.inner.native()?;
1352 let layer_id = maplibre_core::string::string_view(layer_id);
1353 maplibre_core::check(unsafe {
1355 sys::mln_map_set_layer_max_zoom(map, layer_id.raw(), max_zoom)
1356 })
1357 }
1358
1359 pub fn layer_max_zoom(&self, layer_id: &str) -> Result<f64> {
1363 let map = self.inner.native()?;
1364 let layer_id = maplibre_core::string::string_view(layer_id);
1365 let mut max_zoom = 0.0;
1366 maplibre_core::check(unsafe {
1369 sys::mln_map_get_layer_max_zoom(map, layer_id.raw(), &mut max_zoom)
1370 })?;
1371 Ok(max_zoom)
1372 }
1373
1374 pub fn set_layer_visibility(
1376 &self,
1377 layer_id: &str,
1378 visibility: StyleLayerVisibility,
1379 ) -> Result<()> {
1380 let map = self.inner.native()?;
1381 let layer_id = maplibre_core::string::string_view(layer_id);
1382 maplibre_core::check(unsafe {
1384 sys::mln_map_set_layer_visibility(map, layer_id.raw(), visibility.raw_value())
1385 })
1386 }
1387
1388 pub fn layer_visibility(&self, layer_id: &str) -> Result<StyleLayerVisibility> {
1390 let map = self.inner.native()?;
1391 let layer_id = maplibre_core::string::string_view(layer_id);
1392 let mut visibility = 0;
1393 maplibre_core::check(unsafe {
1396 sys::mln_map_get_layer_visibility(map, layer_id.raw(), &mut visibility)
1397 })?;
1398 Ok(StyleLayerVisibility::from_raw(visibility))
1399 }
1400
1401 pub fn style_source_ids(&self) -> Result<Vec<String>> {
1403 let map = self.inner.native()?;
1404 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_id_list>::new();
1405 maplibre_core::check(unsafe { sys::mln_map_list_style_source_ids(map, out.as_mut_ptr()) })?;
1409 unsafe { maplibre_core::style::copy_style_id_list(out.into_live("mln_style_id_list")?) }
1412 }
1413
1414 pub fn style_layer_ids(&self) -> Result<Vec<String>> {
1416 let map = self.inner.native()?;
1417 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_style_id_list>::new();
1418 maplibre_core::check(unsafe { sys::mln_map_list_style_layer_ids(map, out.as_mut_ptr()) })?;
1422 unsafe { maplibre_core::style::copy_style_id_list(out.into_live("mln_style_id_list")?) }
1425 }
1426}
1427
1428unsafe fn copy_text(
1436 copy: impl Fn(*mut std::os::raw::c_char, usize, *mut usize) -> sys::mln_status,
1437) -> Result<String> {
1438 let mut required = 0;
1439 maplibre_core::check(copy(ptr::null_mut(), 0, &mut required))?;
1440 if required == 0 {
1441 return Ok(String::new());
1442 }
1443
1444 let mut buffer = vec![0u8; required];
1445 let mut copied = 0;
1446 maplibre_core::check(copy(buffer.as_mut_ptr().cast(), buffer.len(), &mut copied))?;
1447 if copied > buffer.len() {
1448 return Err(Error::new(
1449 ErrorKind::NativeError,
1450 None,
1451 "native text size exceeded caller buffer",
1452 ));
1453 }
1454 buffer.truncate(copied);
1455 String::from_utf8(buffer).map_err(|_| {
1456 Error::new(
1457 ErrorKind::NativeError,
1458 None,
1459 "native text was not valid UTF-8",
1460 )
1461 })
1462}
1463
1464unsafe fn copy_bytes(
1471 copy: impl Fn(*mut u8, usize, *mut usize) -> sys::mln_status,
1472) -> Result<Vec<u8>> {
1473 let mut required = 0;
1474 maplibre_core::check(copy(ptr::null_mut(), 0, &mut required))?;
1475 if required == 0 {
1476 return Ok(Vec::new());
1477 }
1478
1479 let mut buffer = vec![0u8; required];
1480 let mut copied = 0;
1481 maplibre_core::check(copy(buffer.as_mut_ptr(), buffer.len(), &mut copied))?;
1482 if copied > buffer.len() {
1483 return Err(Error::new(
1484 ErrorKind::NativeError,
1485 None,
1486 "native byte size exceeded caller buffer",
1487 ));
1488 }
1489 buffer.truncate(copied);
1490 Ok(buffer)
1491}