1#![deny(unsafe_op_in_unsafe_fn)]
9
10mod camera;
11mod custom_geometry;
12mod events;
13mod geojson;
14mod handle;
15mod logging;
16mod map;
17mod options;
18mod projection;
19mod render;
20mod resource;
21mod runtime;
22mod values;
23
24use crate::values::NativeValue;
25use maplibre_native_ffi_core as maplibre_core;
26use maplibre_native_ffi_sys as sys;
27
28pub use camera::{
29 AnimationOptions, BoundOptions, BoundsConstraint, CameraFitOptions, CameraOptions,
30 FreeCameraOptions, ProjectionMode,
31};
32pub use custom_geometry::{CanonicalTileId, CustomGeometrySourceOptions};
33pub use events::{
34 CameraTransitionFinishedEvent, MapId, OfflineOperationCompletedEvent,
35 OfflineRegionResponseErrorEvent, OfflineRegionStatus, OfflineRegionStatusEvent,
36 OfflineRegionTileCountLimitEvent, RenderFrameEvent, RenderMapEvent, RenderingStats,
37 RuntimeEvent, RuntimeEventBatch, RuntimeEventPayload, RuntimeEventRef, RuntimeEventSource,
38 TileActionEvent, TileId, UnknownRuntimeEventPayload,
39};
40pub use geojson::GeoJsonSourceDataHandle;
41pub use logging::{LogRecord, clear_log_callback, set_async_log_severity_mask, set_log_callback};
42pub use map::{
43 GeoJsonSourceOptions, ImageContent, ImageStretch, LocationIndicatorImageKind, MapAttachRef,
44 MapHandle, RasterDemEncoding, SourceInfo, SourceType, StyleImage, StyleImageInfo,
45 StyleImageOptions, StyleImageTextFit, StyleLayerVisibility, StyleTransitionOptions,
46 TileJsonInfo, TileScheme, TileSourceOptions, VectorTileEncoding,
47};
48pub use maplibre_core::{
49 AmbientCacheOperation, CameraChangeMode, ConstrainMode, Error, ErrorKind, LogEvent,
50 LogSeverity, LogSeverityMask, MapDebugOptions, MapMode, MapOptions, MapTileOptions,
51 MapViewportOptions, NetworkStatus, NorthOrientation, OfflineOperationKind,
52 OfflineOperationResultKind, OfflineRegionDownloadState, OpenGLClientApi,
53 OpenGLContextOwnership, OpenGLContextProviderMask, RenderBackendMask, RenderMode, RenderResult,
54 ResourceErrorReason, ResourceKind, ResourceLoadingMethod, ResourcePriority,
55 ResourceResponseStatus, ResourceStoragePolicy, ResourceUsage, Result, RuntimeEventMask,
56 RuntimeEventType, TileLodMode, TileOperation, ViewportMode,
57};
58pub use maplibre_native_ffi_core::handle::{NativeHandleLeak, set_leak_reporter};
59pub use projection::MapProjectionHandle;
60pub use render::{
61 DetachedRenderSessionHandle, EglContextDescriptor, FeatureStateSelector, FrameNativePointer,
62 FrameOpenGLTextureName, MetalBorrowedTextureDescriptor, MetalContextDescriptor,
63 MetalOwnedTextureDescriptor, MetalOwnedTextureFrame, MetalOwnedTextureFrameHandle,
64 MetalSurfaceDescriptor, NativePointer, OpenGLBorrowedTextureDescriptor,
65 OpenGLContextDescriptor, OpenGLOwnedTextureDescriptor, OpenGLOwnedTextureFrame,
66 OpenGLOwnedTextureFrameHandle, OpenGLSurfaceDescriptor, PremultipliedRgba8Image,
67 QueriedFeature, RenderSessionHandle, RenderTargetExtent, RenderUpdate,
68 RenderedFeatureQueryOptions, RenderedQueryGeometry, SourceFeatureQueryOptions,
69 TextureImageInfo, VulkanBorrowedTextureDescriptor, VulkanContextDescriptor,
70 VulkanOwnedTextureDescriptor, VulkanOwnedTextureFrame, VulkanOwnedTextureFrameHandle,
71 VulkanSurfaceDescriptor, WebGlContextDescriptor, WebGpuBorrowedTextureDescriptor,
72 WebGpuContextDescriptor, WebGpuOwnedTextureDescriptor, WebGpuOwnedTextureFrame,
73 WebGpuOwnedTextureFrameHandle, WebGpuSurfaceDescriptor, WglContextDescriptor,
74};
75pub use resource::{
76 ByteRange, HttpHeader, HttpHeaderTransformRequest, ResourceProviderDecision, ResourceRequest,
77 ResourceRequestHandle, ResourceResponse, ResourceTransformRequest,
78};
79pub use runtime::{
80 OfflineOperationHandle, OfflineRegionDefinition, OfflineRegionInfo, RuntimeHandle,
81 RuntimeOptions, WakeSource,
82};
83pub use values::{
84 EdgeInsets, LatLng, LatLngBounds, ProjectedMeters, Quaternion, ScreenBox, ScreenPoint,
85 UnitBezier, Vec3,
86};
87
88#[derive(Debug)]
91pub struct HandleOperationError<T> {
92 error: Error,
93 handle: T,
94}
95
96impl<T> HandleOperationError<T> {
97 pub(crate) fn new(error: Error, handle: T) -> Self {
98 Self { error, handle }
99 }
100
101 pub fn error(&self) -> &Error {
103 &self.error
104 }
105
106 pub fn kind(&self) -> ErrorKind {
108 self.error.kind()
109 }
110
111 pub fn raw_status(&self) -> Option<i32> {
113 self.error.raw_status()
114 }
115
116 pub fn diagnostic(&self) -> &str {
118 self.error.diagnostic()
119 }
120
121 pub fn into_error(self) -> Error {
123 self.error
124 }
125
126 pub fn into_handle(self) -> T {
128 self.handle
129 }
130
131 pub fn into_parts(self) -> (Error, T) {
133 (self.error, self.handle)
134 }
135}
136
137impl<T> std::fmt::Display for HandleOperationError<T> {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 self.error.fmt(f)
140 }
141}
142
143impl<T: std::fmt::Debug> std::error::Error for HandleOperationError<T> {}
144
145#[derive(Debug)]
147pub enum OfflineOperationTakeError<T> {
148 Retryable(HandleOperationError<T>),
150 Consumed(Error),
152}
153
154impl<T> OfflineOperationTakeError<T> {
155 pub(crate) fn retryable(error: Error, handle: T) -> Self {
156 Self::Retryable(HandleOperationError::new(error, handle))
157 }
158
159 pub(crate) fn consumed(error: Error) -> Self {
160 Self::Consumed(error)
161 }
162
163 pub fn error(&self) -> &Error {
165 match self {
166 Self::Retryable(error) => error.error(),
167 Self::Consumed(error) => error,
168 }
169 }
170
171 pub fn kind(&self) -> ErrorKind {
173 self.error().kind()
174 }
175
176 pub fn raw_status(&self) -> Option<i32> {
178 self.error().raw_status()
179 }
180
181 pub fn diagnostic(&self) -> &str {
183 self.error().diagnostic()
184 }
185
186 pub fn into_retryable(self) -> Option<HandleOperationError<T>> {
188 match self {
189 Self::Retryable(error) => Some(error),
190 Self::Consumed(_) => None,
191 }
192 }
193
194 pub fn into_error(self) -> Error {
196 match self {
197 Self::Retryable(error) => error.into_error(),
198 Self::Consumed(error) => error,
199 }
200 }
201}
202
203impl<T> std::fmt::Display for OfflineOperationTakeError<T> {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 self.error().fmt(f)
206 }
207}
208
209impl<T: std::fmt::Debug> std::error::Error for OfflineOperationTakeError<T> {}
210
211pub fn c_version() -> u32 {
213 unsafe { sys::mln_c_version() }
216}
217
218pub fn supported_render_backends() -> RenderBackendMask {
220 let mask = unsafe { sys::mln_supported_render_backend_mask() };
223 RenderBackendMask::from_bits_retain(mask)
224}
225
226pub fn supported_opengl_context_providers() -> OpenGLContextProviderMask {
228 let mask = unsafe { sys::mln_opengl_supported_context_provider_mask() };
231 OpenGLContextProviderMask::from_bits_retain(mask)
232}
233
234pub fn projected_meters_for_lat_lng(coordinate: LatLng) -> Result<ProjectedMeters> {
236 let mut raw_meters = sys::mln_projected_meters {
237 northing: 0.0,
238 easting: 0.0,
239 };
240 maplibre_core::check(unsafe {
243 sys::mln_projected_meters_for_lat_lng(coordinate.to_native(), &mut raw_meters)
244 })?;
245 Ok(ProjectedMeters::from_native(raw_meters))
246}
247
248pub fn lat_lng_for_projected_meters(meters: ProjectedMeters) -> Result<LatLng> {
250 let mut raw_coordinate = sys::mln_lat_lng {
251 latitude: 0.0,
252 longitude: 0.0,
253 };
254 maplibre_core::check(unsafe {
257 sys::mln_lat_lng_for_projected_meters(meters.to_native(), &mut raw_coordinate)
258 })?;
259 Ok(LatLng::from_native(raw_coordinate))
260}
261
262pub fn network_status() -> Result<NetworkStatus> {
264 maplibre_core::network_status()
265}
266
267pub fn set_network_status(status: NetworkStatus) -> Result<()> {
269 maplibre_core::set_network_status(status)
270}
271
272#[cfg(test)]
273fn set_network_status_raw(raw_status: u32) -> Result<()> {
274 maplibre_core::set_network_status_raw(raw_status)
275}
276
277#[cfg(test)]
278mod tests {
279 use static_assertions::{assert_impl_all, assert_not_impl_any};
280
281 use super::*;
282
283 assert_not_impl_any!(RuntimeHandle: Send, Sync);
284 assert_not_impl_any!(MapHandle: Send, Sync);
285 assert_not_impl_any!(MapProjectionHandle: Send, Sync);
286 assert_not_impl_any!(NativePointer: Send, Sync);
287 assert_not_impl_any!(FrameNativePointer<'static>: Send, Sync);
288 assert_not_impl_any!(RenderSessionHandle: Send, Sync);
289 assert_not_impl_any!(DetachedRenderSessionHandle: Send, Sync);
290 assert_impl_all!(MapAttachRef: Send, Sync);
293
294 #[test]
295 fn projected_meter_helpers_round_trip() {
297 let coordinate = LatLng::new(45.0, -122.0);
298 let meters = projected_meters_for_lat_lng(coordinate).unwrap();
299 let round_tripped = lat_lng_for_projected_meters(meters).unwrap();
300
301 assert!((round_tripped.latitude - coordinate.latitude).abs() < 1e-9);
302 assert!((round_tripped.longitude - coordinate.longitude).abs() < 1e-9);
303 }
304
305 #[test]
306 fn invalid_network_status_reports_public_error() {
308 let error = set_network_status_raw(999_999).unwrap_err();
309
310 assert_eq!(error.kind(), ErrorKind::InvalidArgument);
311 assert_eq!(error.raw_status(), Some(sys::MLN_STATUS_INVALID_ARGUMENT));
312 assert!(error.diagnostic().contains("network status"));
313 }
314
315 #[test]
316 fn unknown_network_status_is_rejected_before_calling_c() {
318 let error = set_network_status(NetworkStatus::Unknown(999_999)).unwrap_err();
319
320 assert_eq!(error.kind(), ErrorKind::InvalidArgument);
321 assert_eq!(error.raw_status(), None);
322 assert!(error.diagnostic().contains("cannot be set"));
323 }
324}