Skip to main content

maplibre_native_ffi/generated/
values.rs

1// Generated from C headers by tools/bindgen. Do not edit.
2use super::*;
3
4/// How a gesture's zoom, bearing, or pitch keeps changing after release.
5///
6/// See `mln_anchored_momentum` in the
7/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
8#[derive(Debug, Clone, Copy, PartialEq, Default)]
9pub struct AnchoredMomentum {
10    /// How fast the value changed at release: zoom levels per second for zoom,
11    /// and degrees per second for bearing and pitch. The part moves only when
12    /// this is set.
13    pub velocity: Option<f64>,
14    /// The screen point that the change keeps in place. Without one, the change
15    /// keeps the center of the view in place.
16    pub anchor: Option<ScreenPoint>,
17    pub decay: MomentumDecay,
18    /// Where the part settles. Without this, it stays where the gesture and its
19    /// glide leave it.
20    pub snap: Option<MomentumSnap>,
21}
22impl ToNative<sys::mln_anchored_momentum> for AnchoredMomentum {
23    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_anchored_momentum> {
24        let mut raw: sys::mln_anchored_momentum = unsafe { std::mem::zeroed() };
25        raw.fields = 0;
26        if let Some(item) = &self.velocity {
27            raw.fields |= sys::MLN_ANCHORED_MOMENTUM_VELOCITY;
28            raw.velocity = *item;
29        }
30        if let Some(item) = &self.anchor {
31            raw.fields |= sys::MLN_ANCHORED_MOMENTUM_ANCHOR;
32            raw.anchor = to_native(&*item, arena)?;
33        }
34        raw.decay = to_native(&self.decay, arena)?;
35        if let Some(item) = &self.snap {
36            raw.fields |= sys::MLN_ANCHORED_MOMENTUM_SNAP;
37            raw.snap = to_native(&*item, arena)?;
38        }
39        Ok(raw)
40    }
41}
42
43/// The Android hardware buffer of an acquired frame.
44///
45/// See `mln_android_hardware_buffer_frame` in the
46/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/android_8h.html).
47#[derive(Debug, Clone, Copy, PartialEq, Default)]
48pub struct AndroidHardwareBufferFrame {
49    pub width: u32,
50    pub height: u32,
51    pub scale_factor: f64,
52    /// The buffer's index in the ring.
53    pub slot: u32,
54    /// The `AHardwareBuffer*`.
55    pub buffer: *mut std::ffi::c_void,
56}
57impl FromNative<sys::mln_android_hardware_buffer_frame> for AndroidHardwareBufferFrame {
58    unsafe fn from_native(raw: sys::mln_android_hardware_buffer_frame) -> Result<Self> {
59        Ok(Self {
60            width: raw.width,
61            height: raw.height,
62            scale_factor: raw.scale_factor,
63            slot: raw.slot,
64            buffer: raw.buffer,
65        })
66    }
67}
68
69/// A ring of Android hardware buffers that the library allocates, for
70/// `MapHandle::attach_android_hardware_buffer_ring()`.
71///
72/// Each buffer has the map's size in pixels, `logical_size` times the map's
73/// scale factor, and the format AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM. Its
74/// usage is AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT,
75/// AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, and the bits of `usage`.
76///
77/// See `mln_android_hardware_buffer_ring_descriptor` in the
78/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/android_8h.html).
79#[derive(Debug, Clone, Copy, PartialEq)]
80pub struct AndroidHardwareBufferRingDescriptor {
81    pub logical_size: LogicalSize,
82    /// How many buffers the ring has, from 1 to 8.
83    pub buffer_count: u32,
84    /// More `AHARDWAREBUFFER_USAGE_*` bits that your reads need, such as
85    /// AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, or zero.
86    pub usage: u64,
87}
88impl AndroidHardwareBufferRingDescriptor {
89    pub const fn new(logical_size: LogicalSize, buffer_count: u32, usage: u64) -> Self {
90        Self {
91            logical_size,
92            buffer_count,
93            usage,
94        }
95    }
96}
97impl ToNative<sys::mln_android_hardware_buffer_ring_descriptor>
98    for AndroidHardwareBufferRingDescriptor
99{
100    fn to_native(
101        &self,
102        arena: &mut InputArena,
103    ) -> Result<sys::mln_android_hardware_buffer_ring_descriptor> {
104        let mut raw: sys::mln_android_hardware_buffer_ring_descriptor =
105            unsafe { std::mem::zeroed() };
106        raw.size = std::mem::size_of::<sys::mln_android_hardware_buffer_ring_descriptor>() as _;
107        raw.logical_size = to_native(&self.logical_size, arena)?;
108        raw.buffer_count = self.buffer_count;
109        raw.usage = self.usage;
110        Ok(raw)
111    }
112}
113
114/// An Android window to present to, for `MapHandle::attach_android_surface()`.
115///
116/// Name the window by `window`, or by `jni_env` and `surface`. The session
117/// takes its own reference to the window, so you can release yours once the
118/// call returns.
119///
120/// See `mln_android_surface_descriptor` in the
121/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/android_8h.html).
122#[derive(Debug, Clone, Copy, PartialEq)]
123pub struct AndroidSurfaceDescriptor {
124    pub logical_size: LogicalSize,
125    /// Your `ANativeWindow*`, or null to name the window by `surface`.
126    pub window: *mut std::ffi::c_void,
127    /// The calling thread's `JNIEnv*`, with `surface`.
128    pub jni_env: *mut std::ffi::c_void,
129    /// An `android.view.Surface`, with `jni_env`.
130    pub surface: *mut std::ffi::c_void,
131}
132impl AndroidSurfaceDescriptor {
133    pub fn new(logical_size: LogicalSize) -> Self {
134        Self {
135            logical_size,
136            window: Default::default(),
137            jni_env: Default::default(),
138            surface: Default::default(),
139        }
140    }
141}
142impl ToNative<sys::mln_android_surface_descriptor> for AndroidSurfaceDescriptor {
143    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_android_surface_descriptor> {
144        let mut raw: sys::mln_android_surface_descriptor = unsafe { std::mem::zeroed() };
145        raw.size = std::mem::size_of::<sys::mln_android_surface_descriptor>() as _;
146        raw.logical_size = to_native(&self.logical_size, arena)?;
147        raw.window = self.window;
148        raw.jni_env = self.jni_env;
149        raw.surface = self.surface;
150        Ok(raw)
151    }
152}
153
154/// A new Android window for
155/// `RenderSessionHandle::set_android_surface_target()`.
156///
157/// Name the window by `window`, or by `jni_env` and `surface`. The session
158/// takes its own reference to the window, so you can release yours once the
159/// call returns.
160///
161/// See `mln_android_surface_replacement` in the
162/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/android_8h.html).
163#[derive(Debug, Clone, Copy, PartialEq)]
164pub struct AndroidSurfaceReplacement {
165    pub logical_size: LogicalSize,
166    /// Your `ANativeWindow*`, or null to name the window by `surface`.
167    pub window: *mut std::ffi::c_void,
168    /// The calling thread's `JNIEnv*`, with `surface`.
169    pub jni_env: *mut std::ffi::c_void,
170    /// An `android.view.Surface`, with `jni_env`.
171    pub surface: *mut std::ffi::c_void,
172}
173impl AndroidSurfaceReplacement {
174    pub fn new(logical_size: LogicalSize) -> Self {
175        Self {
176            logical_size,
177            window: Default::default(),
178            jni_env: Default::default(),
179            surface: Default::default(),
180        }
181    }
182}
183impl ToNative<sys::mln_android_surface_replacement> for AndroidSurfaceReplacement {
184    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_android_surface_replacement> {
185        let mut raw: sys::mln_android_surface_replacement = unsafe { std::mem::zeroed() };
186        raw.size = std::mem::size_of::<sys::mln_android_surface_replacement>() as _;
187        raw.logical_size = to_native(&self.logical_size, arena)?;
188        raw.window = self.window;
189        raw.jni_env = self.jni_env;
190        raw.surface = self.surface;
191        Ok(raw)
192    }
193}
194
195/// How a camera change animates.
196///
197/// See `mln_animation_options` in the
198/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
199#[derive(Debug, Clone, Default)]
200pub struct AnimationOptions {
201    pub duration_ms: Option<f64>,
202    /// The average speed of a fly animation, in screens per second.
203    /// `duration_ms` overrides it.
204    pub velocity: Option<f64>,
205    /// The zoom level at the peak of a fly animation.
206    pub min_zoom: Option<f64>,
207    pub easing: Option<UnitBezier>,
208    /// An ID that `MapHandle::cancel_camera_transitions_with_id()` cancels the
209    /// change by. Several changes can share one.
210    pub transition_id: Option<u64>,
211    pub end_handler: CameraTransitionHandler,
212}
213impl ToNative<sys::mln_animation_options> for AnimationOptions {
214    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_animation_options> {
215        let mut raw: sys::mln_animation_options = unsafe { std::mem::zeroed() };
216        raw.fields = 0;
217        if let Some(item) = &self.duration_ms {
218            raw.fields |= sys::MLN_ANIMATION_OPTION_DURATION;
219            raw.duration_ms = *item;
220        }
221        if let Some(item) = &self.velocity {
222            raw.fields |= sys::MLN_ANIMATION_OPTION_VELOCITY;
223            raw.velocity = *item;
224        }
225        if let Some(item) = &self.min_zoom {
226            raw.fields |= sys::MLN_ANIMATION_OPTION_MIN_ZOOM;
227            raw.min_zoom = *item;
228        }
229        if let Some(item) = &self.easing {
230            raw.fields |= sys::MLN_ANIMATION_OPTION_EASING;
231            raw.easing = to_native(&*item, arena)?;
232        }
233        if let Some(item) = &self.transition_id {
234            raw.fields |= sys::MLN_ANIMATION_OPTION_TRANSITION_ID;
235            raw.transition_id = *item;
236        }
237        raw.end_handler = to_native(&self.end_handler, arena)?;
238        Ok(raw)
239    }
240}
241
242/// Limits on the camera, for `MapHandle::set_bounds()`.
243///
244/// See `mln_bound_options` in the
245/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
246#[derive(Debug, Clone, Copy, PartialEq, Default)]
247pub struct BoundOptions {
248    /// Removes the area that limits the camera's center.
249    pub unbounded: bool,
250    /// The area that the camera's center stays within.
251    pub bounds: Option<LatLngBounds>,
252    pub min_zoom: Option<f64>,
253    pub max_zoom: Option<f64>,
254    /// The lowest pitch, in degrees.
255    pub min_pitch: Option<f64>,
256    /// The highest pitch, in degrees.
257    pub max_pitch: Option<f64>,
258}
259impl ToNative<sys::mln_bound_options> for BoundOptions {
260    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_bound_options> {
261        let mut raw: sys::mln_bound_options = unsafe { std::mem::zeroed() };
262        raw.size = std::mem::size_of::<sys::mln_bound_options>() as _;
263        raw.fields = 0;
264        convert::set_flag(
265            &mut raw.fields,
266            sys::MLN_BOUND_OPTION_UNBOUNDED,
267            self.unbounded,
268        );
269        if let Some(item) = &self.bounds {
270            raw.fields |= sys::MLN_BOUND_OPTION_BOUNDS;
271            raw.bounds = to_native(&*item, arena)?;
272        }
273        if let Some(item) = &self.min_zoom {
274            raw.fields |= sys::MLN_BOUND_OPTION_MIN_ZOOM;
275            raw.min_zoom = *item;
276        }
277        if let Some(item) = &self.max_zoom {
278            raw.fields |= sys::MLN_BOUND_OPTION_MAX_ZOOM;
279            raw.max_zoom = *item;
280        }
281        if let Some(item) = &self.min_pitch {
282            raw.fields |= sys::MLN_BOUND_OPTION_MIN_PITCH;
283            raw.min_pitch = *item;
284        }
285        if let Some(item) = &self.max_pitch {
286            raw.fields |= sys::MLN_BOUND_OPTION_MAX_PITCH;
287            raw.max_pitch = *item;
288        }
289        Ok(raw)
290    }
291}
292
293native_enum! {
294/// A maintenance action on a runtime's cache database.
295///
296/// The cache database is the file that `RuntimeOptions::cache_path` names. It
297/// holds the ambient cache, meaning the resources that maps loaded, and the
298/// offline regions.
299///
300/// See `mln_cache_database_operation` in the
301/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
302pub enum CacheDatabaseOperation: u32 {
303    /// Deletes the ambient cache's resources and frees the space they used.
304    /// Offline regions keep their resources.
305    Clear = 1,
306    /// Keeps the ambient cache's resources, but makes maps check each one with
307    /// the server before they use it again. Offline regions keep their
308    /// resources as they are.
309    Invalidate = 2,
310    /// Compacts the whole database file to free the disk space that it no
311    /// longer uses.
312    Pack = 3,
313    /// Deletes the whole database, offline regions included, and starts an
314    /// empty one.
315    Reset = 4,
316} Unknown
317}
318
319/// A map's whole camera.
320///
321/// See `mln_camera` in the
322/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
323#[derive(Debug, Clone, Copy, PartialEq, Default)]
324pub struct Camera {
325    pub center: LatLng,
326    /// The altitude of the center, in meters above sea level.
327    pub center_altitude: f64,
328    /// Insets from the map's edges. The camera centers within the rest.
329    pub padding: EdgeInsets,
330    pub zoom: f64,
331    /// The rotation from north, in degrees.
332    pub bearing: f64,
333    /// The tilt toward the horizon, in degrees. 0 looks straight down.
334    pub pitch: f64,
335    /// The roll, in degrees.
336    pub roll: f64,
337    /// The vertical field of view, in degrees.
338    pub field_of_view: f64,
339}
340impl Camera {
341    pub const fn new(
342        center: LatLng,
343        center_altitude: f64,
344        padding: EdgeInsets,
345        zoom: f64,
346        bearing: f64,
347        pitch: f64,
348        roll: f64,
349        field_of_view: f64,
350    ) -> Self {
351        Self {
352            center,
353            center_altitude,
354            padding,
355            zoom,
356            bearing,
357            pitch,
358            roll,
359            field_of_view,
360        }
361    }
362    /// Converts this `Camera` to `CameraOptions` that set each of its members.
363    pub const fn to_options(self) -> CameraOptions {
364        CameraOptions {
365            center: Some(self.center),
366            center_altitude: Some(self.center_altitude),
367            padding: Some(self.padding),
368            anchor: None,
369            zoom: Some(self.zoom),
370            bearing: Some(self.bearing),
371            pitch: Some(self.pitch),
372            roll: Some(self.roll),
373            field_of_view: Some(self.field_of_view),
374        }
375    }
376}
377impl ToNative<sys::mln_camera> for Camera {
378    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera> {
379        let mut raw: sys::mln_camera = unsafe { std::mem::zeroed() };
380        raw.center = to_native(&self.center, arena)?;
381        raw.center_altitude = self.center_altitude;
382        raw.padding = to_native(&self.padding, arena)?;
383        raw.zoom = self.zoom;
384        raw.bearing = self.bearing;
385        raw.pitch = self.pitch;
386        raw.roll = self.roll;
387        raw.field_of_view = self.field_of_view;
388        Ok(raw)
389    }
390}
391impl FromNative<sys::mln_camera> for Camera {
392    unsafe fn from_native(raw: sys::mln_camera) -> Result<Self> {
393        Ok(Self {
394            center: unsafe { from_native(raw.center) }?,
395            center_altitude: raw.center_altitude,
396            padding: unsafe { from_native(raw.padding) }?,
397            zoom: raw.zoom,
398            bearing: raw.bearing,
399            pitch: raw.pitch,
400            roll: raw.roll,
401            field_of_view: raw.field_of_view,
402        })
403    }
404}
405
406/// All the limits on a map's camera.
407///
408/// Its members mean the same as those of `BoundOptions`.
409///
410/// See `mln_camera_bounds` in the
411/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
412#[derive(Debug, Clone, Copy, PartialEq, Default)]
413pub struct CameraBounds {
414    /// The area that the camera's center stays within. When `unbounded` is
415    /// true, it covers the whole world.
416    pub bounds: LatLngBounds,
417    /// Whether no area limits the camera's center.
418    pub unbounded: bool,
419    pub min_zoom: f64,
420    pub max_zoom: f64,
421    /// The lowest pitch, in degrees.
422    pub min_pitch: f64,
423    /// The highest pitch, in degrees.
424    pub max_pitch: f64,
425}
426impl FromNative<sys::mln_camera_bounds> for CameraBounds {
427    unsafe fn from_native(raw: sys::mln_camera_bounds) -> Result<Self> {
428        Ok(Self {
429            bounds: unsafe { from_native(raw.bounds) }?,
430            unbounded: raw.unbounded,
431            min_zoom: raw.min_zoom,
432            max_zoom: raw.max_zoom,
433            min_pitch: raw.min_pitch,
434            max_pitch: raw.max_pitch,
435        })
436    }
437}
438
439native_enum! {
440/// Whether a camera change jumps or animates.
441///
442/// See `mln_camera_change_mode` in the
443/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
444pub enum CameraChangeMode: u32 {
445    Immediate = 0,
446    Animated = 1,
447} Unknown
448}
449impl Default for CameraChangeMode {
450    fn default() -> Self {
451        Self::Immediate
452    }
453}
454
455native_enum! {
456/// What moved the camera.
457///
458/// See `mln_camera_change_source` in the
459/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
460pub enum CameraChangeSource: u32 {
461    /// A camera command outside a gesture, or the map itself, as when a resize
462    /// keeps the camera within its bounds.
463    Command = 0,
464    /// A camera command with a gesture phase.
465    Gesture = 1,
466    /// The momentum and bearing snap that a gesture's end started.
467    Momentum = 2,
468} Unknown
469}
470impl Default for CameraChangeSource {
471    fn default() -> Self {
472        Self::Command
473    }
474}
475
476/// A change to the camera from where it is now, for gestures.
477///
478/// See `mln_camera_delta` in the
479/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
480#[derive(Debug, Clone, Default)]
481pub struct CameraDelta {
482    /// Moves the map's content this far on the screen, as a drag does.
483    pub offset: Option<ScreenPoint>,
484    /// Multiplies the map's scale. 2 zooms in by one level.
485    pub scale: Option<f64>,
486    /// Degrees to add to the bearing.
487    pub bearing: Option<f64>,
488    /// Degrees to add to the pitch.
489    pub pitch: Option<f64>,
490    /// The screen point that `scale`, `bearing`, and `pitch` keep in place. It
491    /// needs one of them, and it combines with `offset` only in a delta without
492    /// a duration.
493    pub anchor: Option<ScreenPoint>,
494    /// How the gesture keeps moving after this delta. Only a delta in the
495    /// `GesturePhase::End` phase carries it.
496    pub momentum: Option<GestureMomentum>,
497    pub animation: AnimationOptions,
498    pub gesture_phase: GesturePhase,
499}
500impl ToNative<sys::mln_camera_delta> for CameraDelta {
501    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_delta> {
502        let mut raw: sys::mln_camera_delta = unsafe { std::mem::zeroed() };
503        raw.size = std::mem::size_of::<sys::mln_camera_delta>() as _;
504        raw.fields = 0;
505        if let Some(item) = &self.offset {
506            raw.fields |= sys::MLN_CAMERA_DELTA_OFFSET;
507            raw.offset = to_native(&*item, arena)?;
508        }
509        if let Some(item) = &self.scale {
510            raw.fields |= sys::MLN_CAMERA_DELTA_SCALE;
511            raw.scale = *item;
512        }
513        if let Some(item) = &self.bearing {
514            raw.fields |= sys::MLN_CAMERA_DELTA_BEARING;
515            raw.bearing = *item;
516        }
517        if let Some(item) = &self.pitch {
518            raw.fields |= sys::MLN_CAMERA_DELTA_PITCH;
519            raw.pitch = *item;
520        }
521        if let Some(item) = &self.anchor {
522            raw.fields |= sys::MLN_CAMERA_DELTA_ANCHOR;
523            raw.anchor = to_native(&*item, arena)?;
524        }
525        if let Some(item) = &self.momentum {
526            raw.fields |= sys::MLN_CAMERA_DELTA_MOMENTUM;
527            raw.momentum = to_native(&*item, arena)?;
528        }
529        raw.animation = to_native(&self.animation, arena)?;
530        raw.gesture_phase = to_native(&self.gesture_phase, arena)?;
531        Ok(raw)
532    }
533}
534
535/// Options for finding the camera that fits an area.
536///
537/// See `mln_camera_fit_options` in the
538/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
539#[derive(Debug, Clone, Copy, PartialEq, Default)]
540pub struct CameraFitOptions {
541    /// Space to leave between the area and each edge of the map. The left and
542    /// right insets must add up to less than the map's width, and the top and
543    /// bottom to less than its height.
544    pub padding: Option<EdgeInsets>,
545    /// The rotation from north, in degrees.
546    pub bearing: Option<f64>,
547    /// The tilt toward the horizon, in degrees.
548    pub pitch: Option<f64>,
549}
550impl ToNative<sys::mln_camera_fit_options> for CameraFitOptions {
551    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_fit_options> {
552        let mut raw: sys::mln_camera_fit_options = unsafe { std::mem::zeroed() };
553        raw.size = std::mem::size_of::<sys::mln_camera_fit_options>() as _;
554        raw.fields = 0;
555        if let Some(item) = &self.padding {
556            raw.fields |= sys::MLN_CAMERA_FIT_OPTION_PADDING;
557            raw.padding = to_native(&*item, arena)?;
558        }
559        if let Some(item) = &self.bearing {
560            raw.fields |= sys::MLN_CAMERA_FIT_OPTION_BEARING;
561            raw.bearing = *item;
562        }
563        if let Some(item) = &self.pitch {
564            raw.fields |= sys::MLN_CAMERA_FIT_OPTION_PITCH;
565            raw.pitch = *item;
566        }
567        Ok(raw)
568    }
569}
570
571/// A camera change that fits an area, for
572/// `MapHandle::fit_camera_to_lat_lng_bounds()` and the other fit commands.
573///
574/// A jump uses only the end handler of `animation`, as in `CameraUpdate`.
575///
576/// See `mln_camera_fit_update` in the
577/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
578#[derive(Debug, Clone, Default)]
579pub struct CameraFitUpdate {
580    pub mode: CameraUpdateMode,
581    pub fit: CameraFitOptions,
582    pub animation: AnimationOptions,
583}
584impl ToNative<sys::mln_camera_fit_update> for CameraFitUpdate {
585    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_fit_update> {
586        let mut raw: sys::mln_camera_fit_update = unsafe { std::mem::zeroed() };
587        raw.size = std::mem::size_of::<sys::mln_camera_fit_update>() as _;
588        raw.mode = to_native(&self.mode, arena)?;
589        raw.fit = to_native(&self.fit, arena)?;
590        raw.animation = to_native(&self.animation, arena)?;
591        Ok(raw)
592    }
593}
594
595/// A camera, with only the members that `fields` selects.
596///
597/// See `mln_camera_options` in the
598/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
599#[derive(Debug, Clone, Copy, PartialEq, Default)]
600pub struct CameraOptions {
601    pub center: Option<LatLng>,
602    /// The altitude of the center, in meters above sea level.
603    pub center_altitude: Option<f64>,
604    /// Insets from the map's edges. The camera centers within the rest.
605    pub padding: Option<EdgeInsets>,
606    /// The screen point that a change to the zoom, bearing, or pitch keeps in
607    /// place. A `center` overrides it.
608    pub anchor: Option<ScreenPoint>,
609    pub zoom: Option<f64>,
610    /// The rotation from north, in degrees.
611    pub bearing: Option<f64>,
612    /// The tilt toward the horizon, in degrees. 0 looks straight down.
613    pub pitch: Option<f64>,
614    /// The roll, in degrees.
615    pub roll: Option<f64>,
616    /// The vertical field of view, in degrees.
617    pub field_of_view: Option<f64>,
618}
619impl ToNative<sys::mln_camera_options> for CameraOptions {
620    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_options> {
621        let mut raw: sys::mln_camera_options = unsafe { std::mem::zeroed() };
622        raw.size = std::mem::size_of::<sys::mln_camera_options>() as _;
623        raw.fields = 0;
624        if let Some(item) = &self.center {
625            raw.fields |= sys::MLN_CAMERA_OPTION_CENTER;
626            raw.center = to_native(&*item, arena)?;
627        }
628        if let Some(item) = &self.center_altitude {
629            raw.fields |= sys::MLN_CAMERA_OPTION_CENTER_ALTITUDE;
630            raw.center_altitude = *item;
631        }
632        if let Some(item) = &self.padding {
633            raw.fields |= sys::MLN_CAMERA_OPTION_PADDING;
634            raw.padding = to_native(&*item, arena)?;
635        }
636        if let Some(item) = &self.anchor {
637            raw.fields |= sys::MLN_CAMERA_OPTION_ANCHOR;
638            raw.anchor = to_native(&*item, arena)?;
639        }
640        if let Some(item) = &self.zoom {
641            raw.fields |= sys::MLN_CAMERA_OPTION_ZOOM;
642            raw.zoom = *item;
643        }
644        if let Some(item) = &self.bearing {
645            raw.fields |= sys::MLN_CAMERA_OPTION_BEARING;
646            raw.bearing = *item;
647        }
648        if let Some(item) = &self.pitch {
649            raw.fields |= sys::MLN_CAMERA_OPTION_PITCH;
650            raw.pitch = *item;
651        }
652        if let Some(item) = &self.roll {
653            raw.fields |= sys::MLN_CAMERA_OPTION_ROLL;
654            raw.roll = *item;
655        }
656        if let Some(item) = &self.field_of_view {
657            raw.fields |= sys::MLN_CAMERA_OPTION_FOV;
658            raw.field_of_view = *item;
659        }
660        Ok(raw)
661    }
662}
663impl FromNative<sys::mln_camera_options> for CameraOptions {
664    unsafe fn from_native(raw: sys::mln_camera_options) -> Result<Self> {
665        Ok(Self {
666            center: unsafe {
667                convert::present(raw.fields, sys::MLN_CAMERA_OPTION_CENTER, raw.center)
668            }?,
669            center_altitude: (raw.fields & sys::MLN_CAMERA_OPTION_CENTER_ALTITUDE != 0)
670                .then_some(raw.center_altitude),
671            padding: unsafe {
672                convert::present(raw.fields, sys::MLN_CAMERA_OPTION_PADDING, raw.padding)
673            }?,
674            anchor: unsafe {
675                convert::present(raw.fields, sys::MLN_CAMERA_OPTION_ANCHOR, raw.anchor)
676            }?,
677            zoom: (raw.fields & sys::MLN_CAMERA_OPTION_ZOOM != 0).then_some(raw.zoom),
678            bearing: (raw.fields & sys::MLN_CAMERA_OPTION_BEARING != 0).then_some(raw.bearing),
679            pitch: (raw.fields & sys::MLN_CAMERA_OPTION_PITCH != 0).then_some(raw.pitch),
680            roll: (raw.fields & sys::MLN_CAMERA_OPTION_ROLL != 0).then_some(raw.roll),
681            field_of_view: (raw.fields & sys::MLN_CAMERA_OPTION_FOV != 0)
682                .then_some(raw.field_of_view),
683        })
684    }
685}
686
687/// A map's camera, with the snapshot generation that it matches.
688///
689/// See `mln_camera_query_result` in the
690/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
691#[derive(Debug, Clone, Copy, PartialEq, Default)]
692pub struct CameraQueryResult {
693    pub generation: u64,
694    pub camera: Camera,
695}
696impl FromNative<sys::mln_camera_query_result> for CameraQueryResult {
697    unsafe fn from_native(raw: sys::mln_camera_query_result) -> Result<Self> {
698        Ok(Self {
699            generation: raw.generation,
700            camera: unsafe { from_native(raw.camera) }?,
701        })
702    }
703}
704
705/// The end of a camera change.
706///
707/// See `mln_camera_transition_end` in the
708/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
709#[derive(Debug, Clone, Copy, PartialEq, Default)]
710pub struct CameraTransitionEnd {
711    pub outcome: CameraTransitionOutcome,
712    /// The generation of the first map snapshot that shows where the change
713    /// left the camera, or 0 when the map closed first.
714    pub generation: u64,
715    /// How fast a gesture's momentum still moved when it was cancelled, which
716    /// the next gesture can add to its own release velocities. Zero for every
717    /// other end.
718    pub velocity: CameraVelocity,
719}
720impl FromNative<sys::mln_camera_transition_end> for CameraTransitionEnd {
721    unsafe fn from_native(raw: sys::mln_camera_transition_end) -> Result<Self> {
722        Ok(Self {
723            outcome: CameraTransitionOutcome::from_raw(raw.outcome),
724            generation: raw.generation,
725            velocity: unsafe { from_native(raw.velocity) }?,
726        })
727    }
728}
729
730/// A callback for the end of a camera change, for `AnimationOptions`.
731///
732/// The callback runs once for each camera command, after every part of the
733/// change that the command started has ended.
734///
735/// See `mln_camera_transition_handler` in the
736/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
737#[derive(Clone, Default)]
738pub struct CameraTransitionHandler {
739    /// The callback receives (`end`).
740    pub callback: Option<std::sync::Arc<dyn Fn(CameraTransitionEnd) + Send + Sync + 'static>>,
741}
742impl std::fmt::Debug for CameraTransitionHandler {
743    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
744        f.debug_struct("CameraTransitionHandler")
745            .finish_non_exhaustive()
746    }
747}
748impl CameraTransitionHandler {
749    pub fn with_callback<F>(mut self, callback: F) -> Self
750    where
751        F: Fn(CameraTransitionEnd) + Send + Sync + 'static,
752    {
753        self.callback = Some(std::sync::Arc::new(callback));
754        self
755    }
756    pub fn new<F>(callback: F) -> Self
757    where
758        F: Fn(CameraTransitionEnd) + Send + Sync + 'static,
759    {
760        Self::default().with_callback(callback)
761    }
762    unsafe extern "C" fn callback_trampoline(
763        user_data: *mut std::ffi::c_void,
764        end: *const sys::mln_camera_transition_end,
765    ) {
766        // SAFETY: native passes the registration that this trampoline's
767        // descriptor transferred.
768        let state = unsafe { callback::state::<Self>(user_data) };
769        callback::invoke("mln_camera_transition_end_callback", (), || {
770            callback::require(&state.callback)?(unsafe { convert::copy_reference(end) }?);
771            Ok(())
772        })
773    }
774}
775impl ToNative<sys::mln_camera_transition_handler> for CameraTransitionHandler {
776    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_transition_handler> {
777        let mut raw: sys::mln_camera_transition_handler = unsafe { std::mem::zeroed() };
778        raw.callback = self
779            .callback
780            .as_ref()
781            .map(|_| Self::callback_trampoline as _);
782        if !(raw.callback.is_none()) {
783            // SAFETY: the release reclaims exactly this state.
784            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
785            raw.release_user_data = Some(callback::release::<Self>);
786        }
787        Ok(raw)
788    }
789}
790
791native_enum! {
792/// How a camera change ended.
793///
794/// A change that ends in more than one way reports
795/// `CameraTransitionOutcome::Cancelled` if any of it was cancelled, and
796/// otherwise `CameraTransitionOutcome::Replaced` if any of it was replaced.
797///
798/// See `mln_camera_transition_outcome` in the
799/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
800pub enum CameraTransitionOutcome: u32 {
801    /// The camera finished the change.
802    Completed = 0,
803    /// `MapHandle::cancel_camera_transitions()`,
804    /// `MapHandle::cancel_camera_transitions_with_id()`, a gesture's
805    /// `GesturePhase::Begin` or `GesturePhase::Cancel`,
806    /// `MapHandle::set_free_camera_options()`, or a resize that moved the
807    /// camera back inside its bounds stopped the change. A command that fails
808    /// before it moves the camera also reports this.
809    Cancelled = 1,
810    /// The map closed before the change ended.
811    Closed = 2,
812    /// A later camera change set every field that a part of the change was
813    /// still animating, so that part stopped. Its other parts keep animating,
814    /// and the change reports this outcome when they end, unless one was
815    /// cancelled.
816    ///
817    /// A later change that sets only some of those fields leaves the change
818    /// animating the rest. A fly's center and zoom count as one field, and so
819    /// do an anchored change's center and the fields that the anchor holds in
820    /// place.
821    Replaced = 3,
822} Unknown
823}
824impl Default for CameraTransitionOutcome {
825    fn default() -> Self {
826        Self::Completed
827    }
828}
829
830/// A camera change for `MapHandle::update_camera()`.
831///
832/// A jump uses only the end handler of `animation`, and the handler runs as
833/// soon as the camera moves.
834///
835/// See `mln_camera_update` in the
836/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
837#[derive(Debug, Clone, Default)]
838pub struct CameraUpdate {
839    pub mode: CameraUpdateMode,
840    pub camera: CameraOptions,
841    pub animation: AnimationOptions,
842    pub gesture_phase: GesturePhase,
843}
844impl ToNative<sys::mln_camera_update> for CameraUpdate {
845    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_camera_update> {
846        let mut raw: sys::mln_camera_update = unsafe { std::mem::zeroed() };
847        raw.size = std::mem::size_of::<sys::mln_camera_update>() as _;
848        raw.mode = to_native(&self.mode, arena)?;
849        raw.camera = to_native(&self.camera, arena)?;
850        raw.animation = to_native(&self.animation, arena)?;
851        raw.gesture_phase = to_native(&self.gesture_phase, arena)?;
852        Ok(raw)
853    }
854}
855
856native_enum! {
857/// How a camera command moves the camera.
858///
859/// See `mln_camera_update_mode` in the
860/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
861pub enum CameraUpdateMode: u32 {
862    /// Moves the camera at once.
863    Jump = 0,
864    /// Animates the camera straight to the target.
865    Ease = 1,
866    /// Zooms out, travels to the target, and zooms back in.
867    Fly = 2,
868} Unknown
869}
870impl Default for CameraUpdateMode {
871    fn default() -> Self {
872        Self::Jump
873    }
874}
875
876/// How fast each part of a camera change moves.
877///
878/// See `mln_camera_velocity` in the
879/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
880#[derive(Debug, Clone, Copy, PartialEq, Default)]
881pub struct CameraVelocity {
882    /// How fast the map's content moves on the screen, in logical pixels per
883    /// second.
884    pub pan: ScreenPoint,
885    /// In zoom levels per second.
886    pub zoom: f64,
887    /// In degrees per second.
888    pub bearing: f64,
889    /// In degrees per second.
890    pub pitch: f64,
891}
892impl FromNative<sys::mln_camera_velocity> for CameraVelocity {
893    unsafe fn from_native(raw: sys::mln_camera_velocity) -> Result<Self> {
894        Ok(Self {
895            pan: unsafe { from_native(raw.pan) }?,
896            zoom: raw.zoom,
897            bearing: raw.bearing,
898            pitch: raw.pitch,
899        })
900    }
901}
902
903/// A tile's zoom level `z`, column `x`, and row `y`, with row 0 at the north.
904///
905/// See `mln_canonical_tile_id` in the
906/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
907#[derive(Debug, Clone, Copy, PartialEq, Default)]
908pub struct CanonicalTileId {
909    pub z: u32,
910    pub x: u32,
911    pub y: u32,
912}
913impl CanonicalTileId {
914    pub const fn new(z: u32, x: u32, y: u32) -> Self {
915        Self { z, x, y }
916    }
917}
918impl ToNative<sys::mln_canonical_tile_id> for CanonicalTileId {
919    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_canonical_tile_id> {
920        let mut raw: sys::mln_canonical_tile_id = unsafe { std::mem::zeroed() };
921        raw.z = self.z;
922        raw.x = self.x;
923        raw.y = self.y;
924        Ok(raw)
925    }
926}
927impl FromNative<sys::mln_canonical_tile_id> for CanonicalTileId {
928    unsafe fn from_native(raw: sys::mln_canonical_tile_id) -> Result<Self> {
929        Ok(Self {
930            z: raw.z,
931            x: raw.x,
932            y: raw.y,
933        })
934    }
935}
936
937native_enum! {
938/// How the map keeps the camera within the world or within its bounds.
939///
940/// See `mln_constrain_mode` in the
941/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
942pub enum ConstrainMode: u32 {
943    None = 0,
944    /// Keeps the world filling the view from top to bottom.
945    HeightOnly = 1,
946    /// Keeps the world filling the view in both directions.
947    WidthAndHeight = 2,
948    /// Keeps the whole view inside the bounds from `MapHandle::set_bounds()`.
949    Screen = 3,
950} Unknown
951}
952impl Default for ConstrainMode {
953    fn default() -> Self {
954        Self::None
955    }
956}
957
958/// The callbacks and options of a custom geometry source.
959///
960/// Zoom levels are whole numbers from 0 to 32.
961///
962/// See `mln_custom_geometry_source_options` in the
963/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
964#[derive(Clone)]
965pub struct CustomGeometrySourceOptions {
966    /// The callback receives (`map`, `source_id`, `tile_id`).
967    pub fetch_tile:
968        std::sync::Arc<dyn Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static>,
969    /// The callback receives (`map`, `source_id`, `tile_id`).
970    pub cancel_tile:
971        Option<std::sync::Arc<dyn Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static>>,
972    pub min_zoom: Option<f64>,
973    pub max_zoom: Option<f64>,
974    /// How far, in pixels, simplified geometry can stray from the original.
975    pub tolerance: Option<f64>,
976    /// The width of a tile in pixels, a power of two no larger than 8192.
977    pub tile_size: Option<u32>,
978    /// The width in pixels of the margin around a tile that holds geometry from
979    /// beyond its edges. `buffer` times 8192 / `tile_size` must be at most
980    /// 65535.
981    pub buffer: Option<u32>,
982    /// Whether to cut geometry at the outer edge of a tile's margin.
983    pub clip: Option<bool>,
984    /// Whether to wrap geometry that crosses the antimeridian.
985    pub wrap: Option<bool>,
986}
987impl std::fmt::Debug for CustomGeometrySourceOptions {
988    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
989        f.debug_struct("CustomGeometrySourceOptions")
990            .finish_non_exhaustive()
991    }
992}
993impl CustomGeometrySourceOptions {
994    pub fn with_cancel_tile<F>(mut self, callback: F) -> Self
995    where
996        F: Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static,
997    {
998        self.cancel_tile = Some(std::sync::Arc::new(callback));
999        self
1000    }
1001    pub fn new<F>(fetch_tile: F) -> Self
1002    where
1003        F: Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static,
1004    {
1005        Self {
1006            fetch_tile: std::sync::Arc::new(fetch_tile),
1007            cancel_tile: None,
1008            min_zoom: Default::default(),
1009            max_zoom: Default::default(),
1010            tolerance: Default::default(),
1011            tile_size: Default::default(),
1012            buffer: Default::default(),
1013            clip: Default::default(),
1014            wrap: Default::default(),
1015        }
1016    }
1017    unsafe extern "C" fn fetch_tile_trampoline(
1018        user_data: *mut std::ffi::c_void,
1019        map: sys::mln_map,
1020        source_id: sys::mln_buffer_view,
1021        tile_id: sys::mln_canonical_tile_id,
1022    ) {
1023        // SAFETY: native passes the registration that this trampoline's
1024        // descriptor transferred.
1025        let state = unsafe { callback::state::<Self>(user_data) };
1026        callback::invoke("mln_custom_source_fetch_tile_callback", (), || {
1027            (state.fetch_tile)(
1028                &*MapHandle::borrow(map)?,
1029                unsafe { crate::string::borrow_string_view(source_id) }?,
1030                unsafe { from_native(tile_id) }?,
1031            );
1032            Ok(())
1033        })
1034    }
1035    unsafe extern "C" fn cancel_tile_trampoline(
1036        user_data: *mut std::ffi::c_void,
1037        map: sys::mln_map,
1038        source_id: sys::mln_buffer_view,
1039        tile_id: sys::mln_canonical_tile_id,
1040    ) {
1041        // SAFETY: native passes the registration that this trampoline's
1042        // descriptor transferred.
1043        let state = unsafe { callback::state::<Self>(user_data) };
1044        callback::invoke("mln_custom_source_cancel_tile_callback", (), || {
1045            callback::require(&state.cancel_tile)?(
1046                &*MapHandle::borrow(map)?,
1047                unsafe { crate::string::borrow_string_view(source_id) }?,
1048                unsafe { from_native(tile_id) }?,
1049            );
1050            Ok(())
1051        })
1052    }
1053}
1054impl ToNative<sys::mln_custom_geometry_source_options> for CustomGeometrySourceOptions {
1055    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_custom_geometry_source_options> {
1056        let mut raw: sys::mln_custom_geometry_source_options = unsafe { std::mem::zeroed() };
1057        raw.fields = 0;
1058        raw.size = std::mem::size_of::<sys::mln_custom_geometry_source_options>() as _;
1059        raw.fetch_tile = Some(Self::fetch_tile_trampoline as _);
1060        raw.cancel_tile = self
1061            .cancel_tile
1062            .as_ref()
1063            .map(|_| Self::cancel_tile_trampoline as _);
1064        if let Some(item) = &self.min_zoom {
1065            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_MIN_ZOOM;
1066            raw.min_zoom = *item;
1067        }
1068        if let Some(item) = &self.max_zoom {
1069            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_MAX_ZOOM;
1070            raw.max_zoom = *item;
1071        }
1072        if let Some(item) = &self.tolerance {
1073            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_TOLERANCE;
1074            raw.tolerance = *item;
1075        }
1076        if let Some(item) = &self.tile_size {
1077            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_TILE_SIZE;
1078            raw.tile_size = *item;
1079        }
1080        if let Some(item) = &self.buffer {
1081            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_BUFFER;
1082            raw.buffer = *item;
1083        }
1084        if let Some(item) = &self.clip {
1085            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_CLIP;
1086            raw.clip = *item;
1087        }
1088        if let Some(item) = &self.wrap {
1089            raw.fields |= sys::MLN_CUSTOM_GEOMETRY_SOURCE_OPTION_WRAP;
1090            raw.wrap = *item;
1091        }
1092        if !(raw.fetch_tile.is_none() && raw.cancel_tile.is_none()) {
1093            // SAFETY: the release reclaims exactly this state.
1094            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
1095            raw.release_user_data = Some(callback::release::<Self>);
1096        }
1097        Ok(raw)
1098    }
1099}
1100
1101/// The callbacks and options of a custom vector source.
1102///
1103/// Zoom levels are whole numbers from 0 to 32.
1104///
1105/// See `mln_custom_vector_source_options` in the
1106/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
1107#[derive(Clone)]
1108pub struct CustomVectorSourceOptions {
1109    /// The callback receives (`map`, `source_id`, `tile_id`).
1110    pub fetch_tile:
1111        std::sync::Arc<dyn Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static>,
1112    /// The callback receives (`map`, `source_id`, `tile_id`).
1113    pub cancel_tile:
1114        Option<std::sync::Arc<dyn Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static>>,
1115    pub min_zoom: Option<f64>,
1116    pub max_zoom: Option<f64>,
1117}
1118impl std::fmt::Debug for CustomVectorSourceOptions {
1119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1120        f.debug_struct("CustomVectorSourceOptions")
1121            .finish_non_exhaustive()
1122    }
1123}
1124impl CustomVectorSourceOptions {
1125    pub fn with_cancel_tile<F>(mut self, callback: F) -> Self
1126    where
1127        F: Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static,
1128    {
1129        self.cancel_tile = Some(std::sync::Arc::new(callback));
1130        self
1131    }
1132    pub fn new<F>(fetch_tile: F) -> Self
1133    where
1134        F: Fn(&MapHandle, &str, CanonicalTileId) + Send + Sync + 'static,
1135    {
1136        Self {
1137            fetch_tile: std::sync::Arc::new(fetch_tile),
1138            cancel_tile: None,
1139            min_zoom: Default::default(),
1140            max_zoom: Default::default(),
1141        }
1142    }
1143    unsafe extern "C" fn fetch_tile_trampoline(
1144        user_data: *mut std::ffi::c_void,
1145        map: sys::mln_map,
1146        source_id: sys::mln_buffer_view,
1147        tile_id: sys::mln_canonical_tile_id,
1148    ) {
1149        // SAFETY: native passes the registration that this trampoline's
1150        // descriptor transferred.
1151        let state = unsafe { callback::state::<Self>(user_data) };
1152        callback::invoke("mln_custom_source_fetch_tile_callback", (), || {
1153            (state.fetch_tile)(
1154                &*MapHandle::borrow(map)?,
1155                unsafe { crate::string::borrow_string_view(source_id) }?,
1156                unsafe { from_native(tile_id) }?,
1157            );
1158            Ok(())
1159        })
1160    }
1161    unsafe extern "C" fn cancel_tile_trampoline(
1162        user_data: *mut std::ffi::c_void,
1163        map: sys::mln_map,
1164        source_id: sys::mln_buffer_view,
1165        tile_id: sys::mln_canonical_tile_id,
1166    ) {
1167        // SAFETY: native passes the registration that this trampoline's
1168        // descriptor transferred.
1169        let state = unsafe { callback::state::<Self>(user_data) };
1170        callback::invoke("mln_custom_source_cancel_tile_callback", (), || {
1171            callback::require(&state.cancel_tile)?(
1172                &*MapHandle::borrow(map)?,
1173                unsafe { crate::string::borrow_string_view(source_id) }?,
1174                unsafe { from_native(tile_id) }?,
1175            );
1176            Ok(())
1177        })
1178    }
1179}
1180impl ToNative<sys::mln_custom_vector_source_options> for CustomVectorSourceOptions {
1181    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_custom_vector_source_options> {
1182        let mut raw: sys::mln_custom_vector_source_options = unsafe { std::mem::zeroed() };
1183        raw.fields = 0;
1184        raw.size = std::mem::size_of::<sys::mln_custom_vector_source_options>() as _;
1185        raw.fetch_tile = Some(Self::fetch_tile_trampoline as _);
1186        raw.cancel_tile = self
1187            .cancel_tile
1188            .as_ref()
1189            .map(|_| Self::cancel_tile_trampoline as _);
1190        if let Some(item) = &self.min_zoom {
1191            raw.fields |= sys::MLN_CUSTOM_VECTOR_SOURCE_OPTION_MIN_ZOOM;
1192            raw.min_zoom = *item;
1193        }
1194        if let Some(item) = &self.max_zoom {
1195            raw.fields |= sys::MLN_CUSTOM_VECTOR_SOURCE_OPTION_MAX_ZOOM;
1196            raw.max_zoom = *item;
1197        }
1198        if !(raw.fetch_tile.is_none() && raw.cancel_tile.is_none()) {
1199            // SAFETY: the release reclaims exactly this state.
1200            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
1201            raw.release_user_data = Some(callback::release::<Self>);
1202        }
1203        Ok(raw)
1204    }
1205}
1206
1207/// A DRM format and modifier that you can import.
1208///
1209/// See `mln_dma_buf_format` in the
1210/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/linux_8h.html).
1211#[derive(Debug, Clone, Copy, PartialEq, Default)]
1212pub struct DmaBufFormat {
1213    /// A DRM fourcc code, such as DRM_FORMAT_ABGR8888.
1214    pub fourcc: u32,
1215    /// A DRM format modifier, such as DRM_FORMAT_MOD_LINEAR.
1216    pub modifier: u64,
1217}
1218impl DmaBufFormat {
1219    pub const fn new(fourcc: u32, modifier: u64) -> Self {
1220        Self { fourcc, modifier }
1221    }
1222}
1223impl ToNative<sys::mln_dma_buf_format> for DmaBufFormat {
1224    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_dma_buf_format> {
1225        let mut raw: sys::mln_dma_buf_format = unsafe { std::mem::zeroed() };
1226        raw.fourcc = self.fourcc;
1227        raw.modifier = self.modifier;
1228        Ok(raw)
1229    }
1230}
1231
1232/// The dmabuf of an acquired frame.
1233///
1234/// See `mln_dma_buf_frame` in the
1235/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/linux_8h.html).
1236#[derive(Debug, Clone, PartialEq, Default)]
1237pub struct DmaBufFrame {
1238    pub width: u32,
1239    pub height: u32,
1240    pub scale_factor: f64,
1241    /// The buffer's index in the ring.
1242    pub slot: u32,
1243    pub fourcc: u32,
1244    pub modifier: u64,
1245    /// The buffer's planes, in the order that its fourcc and modifier define.
1246    /// Import all of them, as EGL_EXT_image_dma_buf_import_modifiers planes 0
1247    /// and up, or with one `zwp_linux_buffer_params_v1.add` call each.
1248    pub planes: Vec<DmaBufPlane>,
1249}
1250impl FromNative<sys::mln_dma_buf_frame> for DmaBufFrame {
1251    unsafe fn from_native(raw: sys::mln_dma_buf_frame) -> Result<Self> {
1252        Ok(Self {
1253            width: raw.width,
1254            height: raw.height,
1255            scale_factor: raw.scale_factor,
1256            slot: raw.slot,
1257            fourcc: raw.fourcc,
1258            modifier: raw.modifier,
1259            planes: unsafe { convert::copy_array(raw.planes, raw.plane_count) }?,
1260        })
1261    }
1262}
1263
1264/// Where one plane of a dmabuf keeps its data.
1265///
1266/// See `mln_dma_buf_plane` in the
1267/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/linux_8h.html).
1268#[derive(Debug, Clone, Copy, PartialEq, Default)]
1269pub struct DmaBufPlane {
1270    /// The file descriptor of the dmabuf that holds the plane. The planes of a
1271    /// buffer often share one.
1272    pub fd: i32,
1273    /// The bytes from the start of the dmabuf to the plane's first byte.
1274    pub offset: u32,
1275    /// The bytes from the start of one row to the start of the next.
1276    pub stride: u32,
1277}
1278impl FromNative<sys::mln_dma_buf_plane> for DmaBufPlane {
1279    unsafe fn from_native(raw: sys::mln_dma_buf_plane) -> Result<Self> {
1280        Ok(Self {
1281            fd: raw.fd,
1282            offset: raw.offset,
1283            stride: raw.stride,
1284        })
1285    }
1286}
1287
1288/// A ring of dmabufs that the library allocates, for
1289/// `MapHandle::attach_dma_buf_ring()`.
1290///
1291/// Each buffer has the map's size in pixels and a format and modifier from
1292/// `formats`. The library renders only DRM_FORMAT_ABGR8888 and
1293/// DRM_FORMAT_ARGB8888. A modifier can give a buffer more planes than its
1294/// format has, such as a plane of compression metadata, and the library takes
1295/// any such modifier that its GPU can render into and share.
1296///
1297/// See `mln_dma_buf_ring_descriptor` in the
1298/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/linux_8h.html).
1299#[derive(Debug, Clone, PartialEq)]
1300pub struct DmaBufRingDescriptor {
1301    pub logical_size: LogicalSize,
1302    /// How many buffers the ring has, from 1 to 8.
1303    pub buffer_count: u32,
1304    /// The formats and modifiers that your reader imports, most preferred
1305    /// first, such as those that eglQueryDmaBufModifiersEXT() reports.
1306    pub formats: Vec<DmaBufFormat>,
1307}
1308impl DmaBufRingDescriptor {
1309    pub fn new(logical_size: LogicalSize, buffer_count: u32, formats: Vec<DmaBufFormat>) -> Self {
1310        Self {
1311            logical_size,
1312            buffer_count,
1313            formats,
1314        }
1315    }
1316}
1317impl ToNative<sys::mln_dma_buf_ring_descriptor> for DmaBufRingDescriptor {
1318    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_dma_buf_ring_descriptor> {
1319        let mut raw: sys::mln_dma_buf_ring_descriptor = unsafe { std::mem::zeroed() };
1320        raw.size = std::mem::size_of::<sys::mln_dma_buf_ring_descriptor>() as _;
1321        raw.logical_size = to_native(&self.logical_size, arena)?;
1322        raw.buffer_count = self.buffer_count;
1323        raw.formats = convert::array(&self.formats, arena)?;
1324        raw.format_count = convert::count(self.formats.len())?;
1325        Ok(raw)
1326    }
1327}
1328
1329/// The DXGI shared texture of an acquired frame.
1330///
1331/// See `mln_dxgi_shared_texture_frame` in the
1332/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/win32_8h.html).
1333#[derive(Debug, Clone, Copy, PartialEq, Default)]
1334pub struct DxgiSharedTextureFrame {
1335    pub width: u32,
1336    pub height: u32,
1337    pub scale_factor: f64,
1338    /// The texture's index in the ring.
1339    pub slot: u32,
1340    /// The texture's `DXGI_FORMAT`.
1341    pub format: u32,
1342    /// The texture's shared NT `HANDLE`.
1343    pub handle: *mut std::ffi::c_void,
1344}
1345impl FromNative<sys::mln_dxgi_shared_texture_frame> for DxgiSharedTextureFrame {
1346    unsafe fn from_native(raw: sys::mln_dxgi_shared_texture_frame) -> Result<Self> {
1347        Ok(Self {
1348            width: raw.width,
1349            height: raw.height,
1350            scale_factor: raw.scale_factor,
1351            slot: raw.slot,
1352            format: raw.format,
1353            handle: raw.handle,
1354        })
1355    }
1356}
1357
1358/// A ring of DXGI shared textures that the library allocates, for
1359/// `MapHandle::attach_dxgi_shared_texture_ring()`.
1360///
1361/// Each texture is a D3D11 2D texture with the map's size in pixels and the
1362/// format DXGI_FORMAT_B8G8R8A8_UNORM. It binds as a shader resource and a
1363/// render target, and is shared through an NT handle.
1364///
1365/// See `mln_dxgi_shared_texture_ring_descriptor` in the
1366/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/win32_8h.html).
1367#[derive(Debug, Clone, Copy, PartialEq)]
1368pub struct DxgiSharedTextureRingDescriptor {
1369    pub logical_size: LogicalSize,
1370    /// How many textures the ring has, from 1 to 8.
1371    pub texture_count: u32,
1372}
1373impl DxgiSharedTextureRingDescriptor {
1374    pub const fn new(logical_size: LogicalSize, texture_count: u32) -> Self {
1375        Self {
1376            logical_size,
1377            texture_count,
1378        }
1379    }
1380}
1381impl ToNative<sys::mln_dxgi_shared_texture_ring_descriptor> for DxgiSharedTextureRingDescriptor {
1382    fn to_native(
1383        &self,
1384        arena: &mut InputArena,
1385    ) -> Result<sys::mln_dxgi_shared_texture_ring_descriptor> {
1386        let mut raw: sys::mln_dxgi_shared_texture_ring_descriptor = unsafe { std::mem::zeroed() };
1387        raw.size = std::mem::size_of::<sys::mln_dxgi_shared_texture_ring_descriptor>() as _;
1388        raw.logical_size = to_native(&self.logical_size, arena)?;
1389        raw.texture_count = self.texture_count;
1390        Ok(raw)
1391    }
1392}
1393
1394/// Distances in logical pixels from each edge of the map.
1395///
1396/// See `mln_edge_insets` in the
1397/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1398#[derive(Debug, Clone, Copy, PartialEq, Default)]
1399pub struct EdgeInsets {
1400    pub top: f64,
1401    pub left: f64,
1402    pub bottom: f64,
1403    pub right: f64,
1404}
1405impl EdgeInsets {
1406    pub const fn new(top: f64, left: f64, bottom: f64, right: f64) -> Self {
1407        Self {
1408            top,
1409            left,
1410            bottom,
1411            right,
1412        }
1413    }
1414}
1415impl ToNative<sys::mln_edge_insets> for EdgeInsets {
1416    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_edge_insets> {
1417        let mut raw: sys::mln_edge_insets = unsafe { std::mem::zeroed() };
1418        raw.top = self.top;
1419        raw.left = self.left;
1420        raw.bottom = self.bottom;
1421        raw.right = self.right;
1422        Ok(raw)
1423    }
1424}
1425impl FromNative<sys::mln_edge_insets> for EdgeInsets {
1426    unsafe fn from_native(raw: sys::mln_edge_insets) -> Result<Self> {
1427        Ok(Self {
1428            top: raw.top,
1429            left: raw.left,
1430            bottom: raw.bottom,
1431            right: raw.right,
1432        })
1433    }
1434}
1435
1436/// The EGL objects that a render session makes its OpenGL context from.
1437///
1438/// See `mln_egl_context_descriptor` in the
1439/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
1440#[derive(Debug, Clone, Copy, PartialEq)]
1441pub struct EglContextDescriptor {
1442    /// An `EGLDisplay`.
1443    pub display: *mut std::ffi::c_void,
1444    /// An `EGLConfig`.
1445    pub config: *mut std::ffi::c_void,
1446    /// Your `EGLContext`, for a shared context.
1447    pub share_context: *mut std::ffi::c_void,
1448    /// The API of a dedicated context. A shared context uses the API of yours.
1449    pub client_api: OpenGlClientApi,
1450    /// Your `eglGetProcAddress`, or null to use the system's.
1451    pub get_proc_address: *mut std::ffi::c_void,
1452}
1453impl EglContextDescriptor {
1454    pub fn new(display: *mut std::ffi::c_void, config: *mut std::ffi::c_void) -> Self {
1455        Self {
1456            display,
1457            config,
1458            share_context: Default::default(),
1459            client_api: Default::default(),
1460            get_proc_address: Default::default(),
1461        }
1462    }
1463}
1464impl ToNative<sys::mln_egl_context_descriptor> for EglContextDescriptor {
1465    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_egl_context_descriptor> {
1466        let mut raw: sys::mln_egl_context_descriptor = unsafe { std::mem::zeroed() };
1467        raw.display = self.display;
1468        raw.config = self.config;
1469        raw.share_context = self.share_context;
1470        raw.client_api = to_native(&self.client_api, arena)?;
1471        raw.get_proc_address = self.get_proc_address;
1472        Ok(raw)
1473    }
1474}
1475
1476/// The ID of a feature in a source, as the source's data gives it.
1477///
1478/// The map compares feature IDs as text. A number names the same feature as the
1479/// string of its shortest decimal form, so 7, 7.0, and "7" name one feature.
1480///
1481/// See `mln_feature_id` in the
1482/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1483#[derive(Debug, Clone, PartialEq)]
1484pub enum FeatureId<'a> {
1485    StringValue(&'a str),
1486    UintValue(u64),
1487    IntValue(i64),
1488    /// A finite number.
1489    DoubleValue(f64),
1490}
1491impl<'a> ToNative<sys::mln_feature_id> for FeatureId<'a> {
1492    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_feature_id> {
1493        let mut raw: sys::mln_feature_id = unsafe { std::mem::zeroed() };
1494        match self {
1495            FeatureId::StringValue(item) => {
1496                raw.type_ = sys::MLN_FEATURE_ID_TYPE_STRING;
1497                raw.data.string_value = to_native(&(*item), arena)?;
1498            }
1499            FeatureId::UintValue(item) => {
1500                raw.type_ = sys::MLN_FEATURE_ID_TYPE_UINT;
1501                raw.data.uint_value = *item;
1502            }
1503            FeatureId::IntValue(item) => {
1504                raw.type_ = sys::MLN_FEATURE_ID_TYPE_INT;
1505                raw.data.int_value = *item;
1506            }
1507            FeatureId::DoubleValue(item) => {
1508                raw.type_ = sys::MLN_FEATURE_ID_TYPE_DOUBLE;
1509                raw.data.double_value = *item;
1510            }
1511        }
1512        Ok(raw)
1513    }
1514}
1515
1516/// The features whose state to set, read, or remove.
1517///
1518/// See `mln_feature_state_selector` in the
1519/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1520#[derive(Debug, Clone, PartialEq)]
1521pub struct FeatureStateSelector<'a> {
1522    pub source_id: &'a str,
1523    /// The source layer, for a vector source. Empty for other sources.
1524    pub source_layer_id: &'a str,
1525    /// The feature's ID. Setting or reading state needs it. Without it,
1526    /// `MapHandle::remove_feature_state()` removes the state of every feature
1527    /// in the source layer.
1528    pub feature_id: Option<FeatureId<'a>>,
1529    /// The one key that `MapHandle::remove_feature_state()` removes. It needs
1530    /// `feature_id`. Empty removes every key.
1531    pub state_key: &'a str,
1532}
1533impl<'a> FeatureStateSelector<'a> {
1534    pub fn new(source_id: &'a str) -> Self {
1535        Self {
1536            source_id,
1537            source_layer_id: Default::default(),
1538            feature_id: None,
1539            state_key: Default::default(),
1540        }
1541    }
1542}
1543impl<'a> ToNative<sys::mln_feature_state_selector> for FeatureStateSelector<'a> {
1544    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_feature_state_selector> {
1545        let mut raw: sys::mln_feature_state_selector = unsafe { std::mem::zeroed() };
1546        raw.size = std::mem::size_of::<sys::mln_feature_state_selector>() as _;
1547        raw.fields = 0;
1548        raw.source_id = to_native(&self.source_id, arena)?;
1549        raw.source_layer_id = to_native(&self.source_layer_id, arena)?;
1550        if let Some(item) = &self.feature_id {
1551            raw.fields |= sys::MLN_FEATURE_STATE_SELECTOR_FEATURE_ID;
1552            raw.feature_id = to_native(&*item, arena)?;
1553        }
1554        raw.state_key = to_native(&self.state_key, arena)?;
1555        Ok(raw)
1556    }
1557}
1558
1559/// A demand for one frame.
1560///
1561/// See `mln_frame_demand` in the
1562/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
1563#[derive(Debug, Clone, Copy, PartialEq, Default)]
1564pub struct FrameDemand {
1565    pub flags: FrameDemandFlag,
1566    /// A value of your choice that the demand's frame result carries.
1567    pub token: u64,
1568}
1569impl ToNative<sys::mln_frame_demand> for FrameDemand {
1570    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_frame_demand> {
1571        let mut raw: sys::mln_frame_demand = unsafe { std::mem::zeroed() };
1572        raw.size = std::mem::size_of::<sys::mln_frame_demand>() as _;
1573        raw.flags = to_native(&self.flags, arena)?;
1574        raw.token = self.token;
1575        Ok(raw)
1576    }
1577}
1578
1579native_flags! {
1580/// How a frame demand behaves.
1581///
1582/// Without flags, a demand draws a frame when the map changed since the last
1583/// one, and otherwise finishes with `RenderResult::NoUpdate`. A session with a
1584/// surface target shows each frame that it draws.
1585///
1586/// See `mln_frame_demand_flag` in the
1587/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
1588pub struct FrameDemandFlag: u32 {
1589    /// Draws a frame even when nothing changed since the last one. It can't be
1590    /// combined with `FrameDemandFlag::WAIT_FOR_UPDATE`.
1591    const FORCE = 1;
1592    /// When the map has nothing new to draw, waits for its next update instead
1593    /// of finishing with `RenderResult::NoUpdate`.
1594    const WAIT_FOR_UPDATE = 4;
1595}
1596}
1597
1598/// Options for creating a frame pacer.
1599///
1600/// See `mln_frame_pacer_options` in the
1601/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
1602#[derive(Debug, Clone, Copy, PartialEq, Default)]
1603pub struct FramePacerOptions {
1604    /// The most frames per second that the pacer demands, greater than zero.
1605    /// The pacer skips display refreshes to stay within it. By default, it can
1606    /// demand frames at every refresh.
1607    pub maximum_frames_per_second: Option<u32>,
1608}
1609impl ToNative<sys::mln_frame_pacer_options> for FramePacerOptions {
1610    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_frame_pacer_options> {
1611        let mut raw: sys::mln_frame_pacer_options = unsafe { std::mem::zeroed() };
1612        raw.size = std::mem::size_of::<sys::mln_frame_pacer_options>() as _;
1613        raw.fields = 0;
1614        if let Some(item) = &self.maximum_frames_per_second {
1615            raw.fields |= sys::MLN_FRAME_PACER_OPTION_MAXIMUM_FRAMES_PER_SECOND;
1616            raw.maximum_frames_per_second = *item;
1617        }
1618        Ok(raw)
1619    }
1620}
1621
1622/// A map camera's whole position and orientation in three dimensions.
1623///
1624/// Its members mean the same as those of `FreeCameraOptions`.
1625///
1626/// See `mln_free_camera` in the
1627/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1628#[derive(Debug, Clone, Copy, PartialEq, Default)]
1629pub struct FreeCamera {
1630    pub position: Vec3,
1631    pub orientation: Quaternion,
1632}
1633impl FromNative<sys::mln_free_camera> for FreeCamera {
1634    unsafe fn from_native(raw: sys::mln_free_camera) -> Result<Self> {
1635        Ok(Self {
1636            position: unsafe { from_native(raw.position) }?,
1637            orientation: unsafe { from_native(raw.orientation) }?,
1638        })
1639    }
1640}
1641
1642/// The camera's position and orientation in three dimensions.
1643///
1644/// See `mln_free_camera_options` in the
1645/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1646#[derive(Debug, Clone, Copy, PartialEq, Default)]
1647pub struct FreeCameraOptions {
1648    /// The camera's position in Web Mercator units, where the world is 1 wide,
1649    /// (0, 0) is its northwest corner, and (1, 1) is its southeast corner. `z`
1650    /// is the altitude in the same units.
1651    pub position: Option<Vec3>,
1652    /// The camera's rotation from looking straight down with north at the top
1653    /// of the screen.
1654    pub orientation: Option<Quaternion>,
1655}
1656impl ToNative<sys::mln_free_camera_options> for FreeCameraOptions {
1657    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_free_camera_options> {
1658        let mut raw: sys::mln_free_camera_options = unsafe { std::mem::zeroed() };
1659        raw.size = std::mem::size_of::<sys::mln_free_camera_options>() as _;
1660        raw.fields = 0;
1661        if let Some(item) = &self.position {
1662            raw.fields |= sys::MLN_FREE_CAMERA_OPTION_POSITION;
1663            raw.position = to_native(&*item, arena)?;
1664        }
1665        if let Some(item) = &self.orientation {
1666            raw.fields |= sys::MLN_FREE_CAMERA_OPTION_ORIENTATION;
1667            raw.orientation = to_native(&*item, arena)?;
1668        }
1669        Ok(raw)
1670    }
1671}
1672
1673/// Options for a GeoJSON
1674/// \[source\](https://maplibre.org/maplibre-style-spec/sources/#geojson).
1675///
1676/// Zoom levels are whole numbers.
1677///
1678/// See `mln_geo_json_source_options` in the
1679/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
1680#[derive(Debug, Clone, PartialEq, Default)]
1681pub struct GeoJsonSourceOptions {
1682    pub min_zoom: Option<f64>,
1683    pub max_zoom: Option<f64>,
1684    pub tolerance: Option<f64>,
1685    /// The last zoom level that has clusters, at most 30.
1686    pub cluster_max_zoom: Option<f64>,
1687    /// The `clusterProperties` object, or empty for none.
1688    pub cluster_properties: String,
1689    pub buffer: Option<u32>,
1690    pub cluster_radius: Option<u32>,
1691    /// At most 4294967295 on a 32-bit target.
1692    pub cluster_min_points: Option<u64>,
1693    pub line_metrics: Option<bool>,
1694    pub cluster: Option<bool>,
1695}
1696impl ToNative<sys::mln_geo_json_source_options> for GeoJsonSourceOptions {
1697    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_geo_json_source_options> {
1698        let mut raw: sys::mln_geo_json_source_options = unsafe { std::mem::zeroed() };
1699        raw.size = std::mem::size_of::<sys::mln_geo_json_source_options>() as _;
1700        raw.fields = 0;
1701        if let Some(item) = &self.min_zoom {
1702            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_MIN_ZOOM;
1703            raw.min_zoom = *item;
1704        }
1705        if let Some(item) = &self.max_zoom {
1706            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_MAX_ZOOM;
1707            raw.max_zoom = *item;
1708        }
1709        if let Some(item) = &self.tolerance {
1710            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_TOLERANCE;
1711            raw.tolerance = *item;
1712        }
1713        if let Some(item) = &self.cluster_max_zoom {
1714            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_MAX_ZOOM;
1715            raw.cluster_max_zoom = *item;
1716        }
1717        raw.cluster_properties = to_native(&self.cluster_properties, arena)?;
1718        if let Some(item) = &self.buffer {
1719            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_BUFFER;
1720            raw.buffer = *item;
1721        }
1722        if let Some(item) = &self.cluster_radius {
1723            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_RADIUS;
1724            raw.cluster_radius = *item;
1725        }
1726        if let Some(item) = &self.cluster_min_points {
1727            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_MIN_POINTS;
1728            raw.cluster_min_points = *item;
1729        }
1730        if let Some(item) = &self.line_metrics {
1731            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_LINE_METRICS;
1732            raw.line_metrics = *item;
1733        }
1734        if let Some(item) = &self.cluster {
1735            raw.fields |= sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER;
1736            raw.cluster = *item;
1737        }
1738        Ok(raw)
1739    }
1740}
1741impl FromNative<sys::mln_geo_json_source_options> for GeoJsonSourceOptions {
1742    unsafe fn from_native(raw: sys::mln_geo_json_source_options) -> Result<Self> {
1743        Ok(Self {
1744            min_zoom: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_MIN_ZOOM != 0)
1745                .then_some(raw.min_zoom),
1746            max_zoom: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_MAX_ZOOM != 0)
1747                .then_some(raw.max_zoom),
1748            tolerance: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_TOLERANCE != 0)
1749                .then_some(raw.tolerance),
1750            cluster_max_zoom: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_MAX_ZOOM != 0)
1751                .then_some(raw.cluster_max_zoom),
1752            cluster_properties: unsafe { from_native(raw.cluster_properties) }?,
1753            buffer: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_BUFFER != 0)
1754                .then_some(raw.buffer),
1755            cluster_radius: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_RADIUS != 0)
1756                .then_some(raw.cluster_radius),
1757            cluster_min_points: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER_MIN_POINTS
1758                != 0)
1759                .then_some(raw.cluster_min_points),
1760            line_metrics: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_LINE_METRICS != 0)
1761                .then_some(raw.line_metrics),
1762            cluster: (raw.fields & sys::MLN_GEO_JSON_SOURCE_OPTION_CLUSTER != 0)
1763                .then_some(raw.cluster),
1764        })
1765    }
1766}
1767
1768/// How a gesture keeps moving the camera after the user lets go.
1769///
1770/// A part moves only when its velocity is set, and each part slows on its own.
1771/// Every part defaults to `MomentumDecayModel::Friction` with a half-life of
1772/// 140 ms, and these other defaults:
1773///
1774/// - Pan stops at 10 logical pixels per second, needs a release of at least
1775///   200, and counts a release faster than 10000 as 10000.
1776/// - Zoom stops at 0.01 levels per second and moves at most 2.5 levels. Its
1777///   snap settles on the nearest whole level.
1778/// - Bearing stops at 1 degree per second and needs a release of at least 60.
1779///   Its snap settles on north within 7 degrees.
1780/// - Pitch stops at 1 degree per second and needs a release of at least 5. Its
1781///   snap settles flat within 7 degrees.
1782///
1783/// See `mln_gesture_momentum` in the
1784/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1785#[derive(Debug, Clone, Copy, PartialEq, Default)]
1786pub struct GestureMomentum {
1787    pub pan: PanMomentum,
1788    pub zoom: AnchoredMomentum,
1789    pub bearing: AnchoredMomentum,
1790    pub pitch: AnchoredMomentum,
1791}
1792impl ToNative<sys::mln_gesture_momentum> for GestureMomentum {
1793    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_gesture_momentum> {
1794        let mut raw: sys::mln_gesture_momentum = unsafe { std::mem::zeroed() };
1795        raw.pan = to_native(&self.pan, arena)?;
1796        raw.zoom = to_native(&self.zoom, arena)?;
1797        raw.bearing = to_native(&self.bearing, arena)?;
1798        raw.pitch = to_native(&self.pitch, arena)?;
1799        Ok(raw)
1800    }
1801}
1802
1803native_enum! {
1804/// Where a camera change falls in a gesture that the user makes.
1805///
1806/// `GesturePhase::Begin` and `GesturePhase::Update` mark a gesture in progress,
1807/// and `GesturePhase::End` and `GesturePhase::Cancel` end it.
1808///
1809/// See `mln_gesture_phase` in the
1810/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
1811pub enum GesturePhase: u32 {
1812    /// The change isn't part of a gesture.
1813    None = 0,
1814    /// The gesture starts. This cancels every running camera animation before
1815    /// the change applies.
1816    Begin = 1,
1817    /// The gesture continues. To start a gesture that keeps the running camera
1818    /// animations, start it with this phase instead of `GesturePhase::Begin`.
1819    Update = 2,
1820    End = 3,
1821    /// The platform cancelled the gesture. This also cancels every running
1822    /// camera animation after the change applies.
1823    Cancel = 4,
1824} Unknown
1825}
1826impl Default for GesturePhase {
1827    fn default() -> Self {
1828        Self::None
1829    }
1830}
1831
1832/// A point in GPU work that the other side waits for before using a texture.
1833///
1834/// See `mln_gpu_sync` in the
1835/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
1836#[derive(Debug, Clone, Copy, PartialEq, Default)]
1837pub struct GpuSync {
1838    pub kind: GpuSyncKind,
1839    /// The object to wait on, for the kinds that name one.
1840    pub handle: u64,
1841    pub value: u64,
1842}
1843impl ToNative<sys::mln_gpu_sync> for GpuSync {
1844    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_gpu_sync> {
1845        let mut raw: sys::mln_gpu_sync = unsafe { std::mem::zeroed() };
1846        raw.size = std::mem::size_of::<sys::mln_gpu_sync>() as _;
1847        raw.kind = to_native(&self.kind, arena)?;
1848        raw.handle = self.handle;
1849        raw.value = self.value;
1850        Ok(raw)
1851    }
1852}
1853impl FromNative<sys::mln_gpu_sync> for GpuSync {
1854    unsafe fn from_native(raw: sys::mln_gpu_sync) -> Result<Self> {
1855        Ok(Self {
1856            kind: GpuSyncKind::from_raw(raw.kind),
1857            handle: raw.handle,
1858            value: raw.value,
1859        })
1860    }
1861}
1862
1863native_enum! {
1864/// How one side waits for the other's GPU work on a shared texture.
1865///
1866/// A sync file descriptor or an OpenGL fence signals once, so when
1867/// `AcquiredFrameHandle::release()` succeeds, the session takes the one you
1868/// pass. A Vulkan timeline semaphore, Metal shared event, or D3D12 fence counts
1869/// up with each frame, so the one you pass stays yours. Keep it valid until a
1870/// detach or release of the session completes.
1871///
1872/// See `mln_gpu_sync_kind` in the
1873/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
1874pub enum GpuSyncKind: u32 {
1875    /// The work has already finished, so there is nothing to wait for.
1876    CpuComplete = 0,
1877    /// `handle` is a `GLsync` in the session's share group.
1878    OpenGlFence = 1,
1879    /// The work was submitted to the queue that both sides share, so work
1880    /// submitted to that queue later runs after it.
1881    QueueOrder = 2,
1882    /// `handle` is a `VkSemaphore`. Wait until it reaches `value`.
1883    VulkanTimelineSemaphore = 3,
1884    /// `handle` is a sync file descriptor.
1885    SyncFd = 4,
1886    /// `handle` is an `MTLSharedEvent`. Wait until it reaches `value`.
1887    MetalSharedEvent = 5,
1888    /// `handle` is a shared Windows handle to an `ID3D12Fence`. Wait until it
1889    /// reaches `value`.
1890    D3D12Fence = 6,
1891} Unknown
1892}
1893impl Default for GpuSyncKind {
1894    fn default() -> Self {
1895        Self::CpuComplete
1896    }
1897}
1898
1899native_flags! {
1900/// A GPU sync kind, as a bit in a set.
1901///
1902/// See `mln_gpu_sync_kind_flag` in the
1903/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
1904pub struct GpuSyncKindFlag: u32 {
1905    const CPU_COMPLETE = 1;
1906    const OPEN_GL_FENCE = 2;
1907    const QUEUE_ORDER = 4;
1908    const VULKAN_TIMELINE_SEMAPHORE = 8;
1909    const SYNC_FD = 16;
1910    const METAL_SHARED_EVENT = 32;
1911    const D3D12_FENCE = 64;
1912}
1913}
1914
1915/// An HTTP header.
1916///
1917/// `name` follows the rules of `HttpHeaderTransformResponse::set_header()`.
1918///
1919/// See `mln_http_header` in the
1920/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
1921#[derive(Debug, Clone, PartialEq)]
1922pub struct HttpHeader {
1923    pub name: String,
1924    pub value: String,
1925}
1926impl HttpHeader {
1927    pub fn new(name: String) -> Self {
1928        Self {
1929            name,
1930            value: Default::default(),
1931        }
1932    }
1933}
1934impl ToNative<sys::mln_http_header> for HttpHeader {
1935    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_http_header> {
1936        let mut raw: sys::mln_http_header = unsafe { std::mem::zeroed() };
1937        raw.name = to_native(&self.name, arena)?;
1938        raw.value = to_native(&self.value, arena)?;
1939        Ok(raw)
1940    }
1941}
1942
1943/// Headers to add to the HTTP requests whose URL matches a pattern.
1944///
1945/// See `mln_http_header_rule` in the
1946/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
1947#[derive(Debug, Clone, PartialEq, Default)]
1948pub struct HttpHeaderRule {
1949    /// The kinds of resource that the rule covers. Zero covers every kind.
1950    pub kinds: ResourceKindFlag,
1951    pub flags: UrlMatchFlag,
1952    pub url: String,
1953    pub headers: Vec<HttpHeader>,
1954}
1955impl ToNative<sys::mln_http_header_rule> for HttpHeaderRule {
1956    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_http_header_rule> {
1957        let mut raw: sys::mln_http_header_rule = unsafe { std::mem::zeroed() };
1958        raw.size = std::mem::size_of::<sys::mln_http_header_rule>() as _;
1959        raw.kinds = to_native(&self.kinds, arena)?;
1960        raw.flags = to_native(&self.flags, arena)?;
1961        raw.url = to_native(&self.url, arena)?;
1962        raw.headers = convert::array(&self.headers, arena)?;
1963        raw.header_count = convert::count(self.headers.len())?;
1964        Ok(raw)
1965    }
1966}
1967
1968/// Headers to add to HTTP requests, for
1969/// `RuntimeHandle::set_http_header_transform()`.
1970///
1971/// Set either `callback` or `rules`, not both.
1972///
1973/// Runs on a library thread.
1974///
1975/// See `mln_http_header_transform` in the
1976/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
1977#[derive(Clone, Default)]
1978pub struct HttpHeaderTransform {
1979    /// The callback receives (`kind`, `url`, `out_response`).
1980    ///
1981    /// An `Err` of `Error::Status` with a failure status answers native
1982    /// that status. Any other error, or a panic, reaches the reporter and
1983    /// answers `Status::NativeError`.
1984    pub callback: Option<
1985        std::sync::Arc<
1986            dyn Fn(ResourceKind, &str, &mut HttpHeaderTransformResponse<'_>) -> Result<()>
1987                + Send
1988                + Sync
1989                + 'static,
1990        >,
1991    >,
1992    /// The first rule that matches a request adds its headers, and no other.
1993    pub rules: Vec<HttpHeaderRule>,
1994}
1995impl std::fmt::Debug for HttpHeaderTransform {
1996    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1997        f.debug_struct("HttpHeaderTransform")
1998            .finish_non_exhaustive()
1999    }
2000}
2001impl HttpHeaderTransform {
2002    pub fn with_callback<F>(mut self, callback: F) -> Self
2003    where
2004        F: Fn(ResourceKind, &str, &mut HttpHeaderTransformResponse<'_>) -> Result<()>
2005            + Send
2006            + Sync
2007            + 'static,
2008    {
2009        self.callback = Some(std::sync::Arc::new(callback));
2010        self
2011    }
2012    pub fn new<F>(callback: F) -> Self
2013    where
2014        F: Fn(ResourceKind, &str, &mut HttpHeaderTransformResponse<'_>) -> Result<()>
2015            + Send
2016            + Sync
2017            + 'static,
2018    {
2019        Self::default().with_callback(callback)
2020    }
2021    unsafe extern "C" fn callback_trampoline(
2022        user_data: *mut std::ffi::c_void,
2023        kind: sys::mln_resource_kind,
2024        url: sys::mln_buffer_view,
2025        out_response: *mut sys::mln_http_header_transform_response,
2026    ) -> sys::mln_status {
2027        // SAFETY: native passes the registration that this trampoline's
2028        // descriptor transferred.
2029        let state = unsafe { callback::state::<Self>(user_data) };
2030        callback::invoke_status(
2031            "mln_http_header_transform_callback",
2032            sys::MLN_STATUS_NATIVE_ERROR,
2033            || {
2034                Ok(callback::require(&state.callback)?(
2035                    ResourceKind::from_raw(kind),
2036                    unsafe { crate::string::borrow_string_view(url) }?,
2037                    &mut HttpHeaderTransformResponse::new(out_response)?,
2038                ))
2039            },
2040        )
2041    }
2042}
2043impl ToNative<sys::mln_http_header_transform> for HttpHeaderTransform {
2044    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_http_header_transform> {
2045        let mut raw: sys::mln_http_header_transform = unsafe { std::mem::zeroed() };
2046        raw.size = std::mem::size_of::<sys::mln_http_header_transform>() as _;
2047        raw.callback = self
2048            .callback
2049            .as_ref()
2050            .map(|_| Self::callback_trampoline as _);
2051        raw.rules = convert::array(&self.rules, arena)?;
2052        raw.rule_count = convert::count(self.rules.len())?;
2053        if !(raw.callback.is_none()) {
2054            // SAFETY: the release reclaims exactly this state.
2055            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
2056            raw.release_user_data = Some(callback::release::<Self>);
2057        }
2058        Ok(raw)
2059    }
2060}
2061
2062/// A native response borrowed only for one host callback.
2063///
2064/// The headers that an HTTP header transform callback sets.
2065///
2066/// See `mln_http_header_transform_response` in the
2067/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
2068#[derive(Debug)]
2069pub struct HttpHeaderTransformResponse<'a> {
2070    raw: std::ptr::NonNull<sys::mln_http_header_transform_response>,
2071    lifetime: std::marker::PhantomData<&'a mut sys::mln_http_header_transform_response>,
2072}
2073impl HttpHeaderTransformResponse<'_> {
2074    fn new(raw: *mut sys::mln_http_header_transform_response) -> Result<Self> {
2075        let raw = std::ptr::NonNull::new(raw)
2076            .ok_or_else(|| Error::invalid_argument("null callback response"))?;
2077        Ok(Self {
2078            raw,
2079            lifetime: std::marker::PhantomData,
2080        })
2081    }
2082    /// Sets a header on the request that an HTTP header transform callback
2083    /// handles.
2084    ///
2085    /// Header names ignore letter case, and setting a header again replaces its
2086    /// value. `name` can't be a header that the library or the platform
2087    /// manages: `Accept-Encoding`, `Connection`, `Content-Length`, `Host`,
2088    /// `If-Modified-Since`, `If-None-Match`, `Keep-Alive`,
2089    /// `Proxy-Authorization`, `Proxy-Connection`, `Range`, `TE`, `Trailer`,
2090    /// `Transfer-Encoding`, `Upgrade`, or `User-Agent`.
2091    ///
2092    /// See `mln_http_header_transform_response_set_header` in the
2093    /// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
2094    pub fn set_header(&mut self, name: &str, value: &str) -> Result<()> {
2095        let arena = &mut InputArena::default();
2096        let native_name = to_native(&name, arena)?;
2097        let native_value = to_native(&value, arena)?;
2098        crate::error::check(|out_diagnostic| unsafe {
2099            sys::mln_http_header_transform_response_set_header(
2100                self.raw.as_ptr(),
2101                native_name,
2102                native_value,
2103                out_diagnostic,
2104            )
2105        })
2106    }
2107}
2108
2109/// The area of an image, in image pixels, that text fits inside.
2110///
2111/// See `mln_image_content` in the
2112/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
2113#[derive(Debug, Clone, Copy, PartialEq, Default)]
2114pub struct ImageContent {
2115    pub left: f32,
2116    pub top: f32,
2117    pub right: f32,
2118    pub bottom: f32,
2119}
2120impl ImageContent {
2121    pub const fn new(left: f32, top: f32, right: f32, bottom: f32) -> Self {
2122        Self {
2123            left,
2124            top,
2125            right,
2126            bottom,
2127        }
2128    }
2129}
2130impl ToNative<sys::mln_image_content> for ImageContent {
2131    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_image_content> {
2132        let mut raw: sys::mln_image_content = unsafe { std::mem::zeroed() };
2133        raw.left = self.left;
2134        raw.top = self.top;
2135        raw.right = self.right;
2136        raw.bottom = self.bottom;
2137        Ok(raw)
2138    }
2139}
2140impl FromNative<sys::mln_image_content> for ImageContent {
2141    unsafe fn from_native(raw: sys::mln_image_content) -> Result<Self> {
2142        Ok(Self {
2143            left: raw.left,
2144            top: raw.top,
2145            right: raw.right,
2146            bottom: raw.bottom,
2147        })
2148    }
2149}
2150
2151/// A range of image pixels, from `from` to `to`, that stretches to fit text.
2152///
2153/// See `mln_image_stretch` in the
2154/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
2155#[derive(Debug, Clone, Copy, PartialEq, Default)]
2156pub struct ImageStretch {
2157    pub from: f32,
2158    pub to: f32,
2159}
2160impl ImageStretch {
2161    pub const fn new(from: f32, to: f32) -> Self {
2162        Self { from, to }
2163    }
2164}
2165impl ToNative<sys::mln_image_stretch> for ImageStretch {
2166    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_image_stretch> {
2167        let mut raw: sys::mln_image_stretch = unsafe { std::mem::zeroed() };
2168        raw.from = self.from;
2169        raw.to = self.to;
2170        Ok(raw)
2171    }
2172}
2173impl FromNative<sys::mln_image_stretch> for ImageStretch {
2174    unsafe fn from_native(raw: sys::mln_image_stretch) -> Result<Self> {
2175        Ok(Self {
2176            from: raw.from,
2177            to: raw.to,
2178        })
2179    }
2180}
2181
2182/// The IOSurface of an acquired frame.
2183///
2184/// See `mln_io_surface_frame` in the
2185/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/apple_8h.html).
2186#[derive(Debug, Clone, Copy, PartialEq, Default)]
2187pub struct IoSurfaceFrame {
2188    pub width: u32,
2189    pub height: u32,
2190    pub scale_factor: f64,
2191    /// The surface's index in the ring.
2192    pub slot: u32,
2193    /// The `IOSurfaceRef`.
2194    pub surface: *mut std::ffi::c_void,
2195}
2196impl FromNative<sys::mln_io_surface_frame> for IoSurfaceFrame {
2197    unsafe fn from_native(raw: sys::mln_io_surface_frame) -> Result<Self> {
2198        Ok(Self {
2199            width: raw.width,
2200            height: raw.height,
2201            scale_factor: raw.scale_factor,
2202            slot: raw.slot,
2203            surface: raw.surface,
2204        })
2205    }
2206}
2207
2208/// A ring of IOSurfaces that the library allocates, for
2209/// `MapHandle::attach_io_surface_ring()`.
2210///
2211/// Each surface has the map's size in pixels, `logical_size` times the map's
2212/// scale factor, and the pixel format kCVPixelFormatType_32BGRA, which Metal
2213/// names MTLPixelFormatBGRA8Unorm.
2214///
2215/// See `mln_io_surface_ring_descriptor` in the
2216/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/apple_8h.html).
2217#[derive(Debug, Clone, Copy, PartialEq)]
2218pub struct IoSurfaceRingDescriptor {
2219    pub logical_size: LogicalSize,
2220    /// How many surfaces the ring has, from 1 to 8.
2221    pub buffer_count: u32,
2222    /// The MTLDevice to render with. A null device picks the system's default.
2223    pub context: MetalContextDescriptor,
2224}
2225impl IoSurfaceRingDescriptor {
2226    pub fn new(logical_size: LogicalSize, buffer_count: u32) -> Self {
2227        Self {
2228            logical_size,
2229            buffer_count,
2230            context: Default::default(),
2231        }
2232    }
2233}
2234impl ToNative<sys::mln_io_surface_ring_descriptor> for IoSurfaceRingDescriptor {
2235    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_io_surface_ring_descriptor> {
2236        let mut raw: sys::mln_io_surface_ring_descriptor = unsafe { std::mem::zeroed() };
2237        raw.size = std::mem::size_of::<sys::mln_io_surface_ring_descriptor>() as _;
2238        raw.logical_size = to_native(&self.logical_size, arena)?;
2239        raw.buffer_count = self.buffer_count;
2240        raw.context = to_native(&self.context, arena)?;
2241        Ok(raw)
2242    }
2243}
2244
2245/// A geographic coordinate, in degrees.
2246///
2247/// See `mln_lat_lng` in the
2248/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2249#[derive(Debug, Clone, Copy, PartialEq, Default)]
2250pub struct LatLng {
2251    pub latitude: f64,
2252    pub longitude: f64,
2253}
2254impl LatLng {
2255    pub const fn new(latitude: f64, longitude: f64) -> Self {
2256        Self {
2257            latitude,
2258            longitude,
2259        }
2260    }
2261}
2262impl ToNative<sys::mln_lat_lng> for LatLng {
2263    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_lat_lng> {
2264        let mut raw: sys::mln_lat_lng = unsafe { std::mem::zeroed() };
2265        raw.latitude = self.latitude;
2266        raw.longitude = self.longitude;
2267        Ok(raw)
2268    }
2269}
2270impl FromNative<sys::mln_lat_lng> for LatLng {
2271    unsafe fn from_native(raw: sys::mln_lat_lng) -> Result<Self> {
2272        Ok(Self {
2273            latitude: raw.latitude,
2274            longitude: raw.longitude,
2275        })
2276    }
2277}
2278
2279/// A rectangle of coordinates, from its southwest to its northeast corner.
2280///
2281/// See `mln_lat_lng_bounds` in the
2282/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2283#[derive(Debug, Clone, Copy, PartialEq, Default)]
2284pub struct LatLngBounds {
2285    pub southwest: LatLng,
2286    pub northeast: LatLng,
2287}
2288impl LatLngBounds {
2289    pub const fn new(southwest: LatLng, northeast: LatLng) -> Self {
2290        Self {
2291            southwest,
2292            northeast,
2293        }
2294    }
2295}
2296impl ToNative<sys::mln_lat_lng_bounds> for LatLngBounds {
2297    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_lat_lng_bounds> {
2298        let mut raw: sys::mln_lat_lng_bounds = unsafe { std::mem::zeroed() };
2299        raw.southwest = to_native(&self.southwest, arena)?;
2300        raw.northeast = to_native(&self.northeast, arena)?;
2301        Ok(raw)
2302    }
2303}
2304impl FromNative<sys::mln_lat_lng_bounds> for LatLngBounds {
2305    unsafe fn from_native(raw: sys::mln_lat_lng_bounds) -> Result<Self> {
2306        Ok(Self {
2307            southwest: unsafe { from_native(raw.southwest) }?,
2308            northeast: unsafe { from_native(raw.northeast) }?,
2309        })
2310    }
2311}
2312
2313native_enum! {
2314/// The part of the library that logged a message.
2315///
2316/// See `mln_log_event` in the
2317/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/logging_8h.html).
2318pub enum LogEvent: u32 {
2319    General = 0,
2320    Setup = 1,
2321    Shader = 2,
2322    ParseStyle = 3,
2323    ParseTile = 4,
2324    Render = 5,
2325    Style = 6,
2326    Database = 7,
2327    HttpRequest = 8,
2328    Sprite = 9,
2329    Image = 10,
2330    GraphicsBackend = 11,
2331    Jni = 12,
2332    Android = 13,
2333    Crash = 14,
2334    Glyph = 15,
2335    Timing = 16,
2336} Unknown
2337}
2338impl Default for LogEvent {
2339    fn default() -> Self {
2340        Self::General
2341    }
2342}
2343
2344/// A log callback, for `set_log_callback()`.
2345///
2346/// Runs on the thread that logged the message, or on a background thread for
2347/// the severities that `set_log_async_severity_mask()` selects. The callback
2348/// can't call the library.
2349///
2350/// See `mln_log_handler` in the
2351/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/logging_8h.html).
2352#[derive(Clone)]
2353pub struct LogHandler {
2354    /// The callback receives (`severity`, `event`, `code`, `message`).
2355    pub callback: std::sync::Arc<dyn Fn(LogSeverity, LogEvent, i64, &str) + Send + Sync + 'static>,
2356    /// The severities that also go to the platform's log, as they do without a
2357    /// callback. 0 sends none. A message of these severities goes to the
2358    /// platform's log even when the handler's queue can't accept it.
2359    pub platform_severities: LogSeverityFlag,
2360}
2361impl std::fmt::Debug for LogHandler {
2362    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2363        f.debug_struct("LogHandler").finish_non_exhaustive()
2364    }
2365}
2366impl LogHandler {
2367    pub fn new<F>(callback: F) -> Self
2368    where
2369        F: Fn(LogSeverity, LogEvent, i64, &str) + Send + Sync + 'static,
2370    {
2371        Self {
2372            callback: std::sync::Arc::new(callback),
2373            platform_severities: Default::default(),
2374        }
2375    }
2376    unsafe extern "C" fn callback_trampoline(
2377        user_data: *mut std::ffi::c_void,
2378        severity: sys::mln_log_severity,
2379        event: sys::mln_log_event,
2380        code: i64,
2381        message: sys::mln_buffer_view,
2382    ) {
2383        // SAFETY: native passes the registration that this trampoline's
2384        // descriptor transferred.
2385        let state = unsafe { callback::state::<Self>(user_data) };
2386        callback::invoke("mln_log_callback", (), || {
2387            (state.callback)(
2388                LogSeverity::from_raw(severity),
2389                LogEvent::from_raw(event),
2390                code,
2391                unsafe { crate::string::borrow_string_view(message) }?,
2392            );
2393            Ok(())
2394        })
2395    }
2396}
2397impl ToNative<sys::mln_log_handler> for LogHandler {
2398    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_log_handler> {
2399        let mut raw: sys::mln_log_handler = unsafe { std::mem::zeroed() };
2400        raw.size = std::mem::size_of::<sys::mln_log_handler>() as _;
2401        raw.callback = Some(Self::callback_trampoline as _);
2402        raw.platform_severities = to_native(&self.platform_severities, arena)?;
2403        if !(raw.callback.is_none()) {
2404            // SAFETY: the release reclaims exactly this state.
2405            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
2406            raw.release_user_data = Some(callback::release::<Self>);
2407        }
2408        Ok(raw)
2409    }
2410}
2411
2412native_enum! {
2413/// The severity of a log message.
2414///
2415/// See `mln_log_severity` in the
2416/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/logging_8h.html).
2417pub enum LogSeverity: u32 {
2418    Info = 1,
2419    Warning = 2,
2420    Error = 3,
2421} Unknown
2422}
2423
2424native_flags! {
2425/// A log severity, as a bit in a set.
2426///
2427/// See `mln_log_severity_flag` in the
2428/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/logging_8h.html).
2429pub struct LogSeverityFlag: u32 {
2430    const INFO = 2;
2431    const WARNING = 4;
2432    const ERROR = 8;
2433    /// The severities logged on a background thread until
2434    /// `set_log_async_severity_mask()` changes them.
2435    const DEFAULT = 6;
2436    const ALL = 14;
2437}
2438}
2439
2440/// A size in logical pixels, and the physical pixels in each logical pixel.
2441///
2442/// See `mln_logical_extent` in the
2443/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2444#[derive(Debug, Clone, Copy, PartialEq, Default)]
2445pub struct LogicalExtent {
2446    pub width: u32,
2447    pub height: u32,
2448    pub scale_factor: f64,
2449}
2450impl LogicalExtent {
2451    pub const fn new(width: u32, height: u32, scale_factor: f64) -> Self {
2452        Self {
2453            width,
2454            height,
2455            scale_factor,
2456        }
2457    }
2458}
2459impl ToNative<sys::mln_logical_extent> for LogicalExtent {
2460    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_logical_extent> {
2461        let mut raw: sys::mln_logical_extent = unsafe { std::mem::zeroed() };
2462        raw.width = self.width;
2463        raw.height = self.height;
2464        raw.scale_factor = self.scale_factor;
2465        Ok(raw)
2466    }
2467}
2468impl FromNative<sys::mln_logical_extent> for LogicalExtent {
2469    unsafe fn from_native(raw: sys::mln_logical_extent) -> Result<Self> {
2470        Ok(Self {
2471            width: raw.width,
2472            height: raw.height,
2473            scale_factor: raw.scale_factor,
2474        })
2475    }
2476}
2477
2478/// A size in logical pixels, which the map's scale factor turns into pixels.
2479///
2480/// See `mln_logical_size` in the
2481/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2482#[derive(Debug, Clone, Copy, PartialEq, Default)]
2483pub struct LogicalSize {
2484    pub width: u32,
2485    pub height: u32,
2486}
2487impl LogicalSize {
2488    pub const fn new(width: u32, height: u32) -> Self {
2489        Self { width, height }
2490    }
2491}
2492impl ToNative<sys::mln_logical_size> for LogicalSize {
2493    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_logical_size> {
2494        let mut raw: sys::mln_logical_size = unsafe { std::mem::zeroed() };
2495        raw.width = self.width;
2496        raw.height = self.height;
2497        Ok(raw)
2498    }
2499}
2500
2501native_flags! {
2502/// A debug overlay that the map draws.
2503///
2504/// See `mln_map_debug_flag` in the
2505/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2506pub struct MapDebugFlag: u32 {
2507    const TILE_BORDERS = 2;
2508    const PARSE_STATUS = 4;
2509    const TIMESTAMPS = 8;
2510    const COLLISION = 16;
2511    const OVERDRAW = 32;
2512    const STENCIL_CLIP = 64;
2513    const DEPTH_BUFFER = 128;
2514}
2515}
2516
2517native_enum! {
2518/// Why a map failed to load a style.
2519///
2520/// See `mln_map_load_error` in the
2521/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
2522pub enum MapLoadError: u32 {
2523    Unknown = 0,
2524    /// The style document isn't a valid style.
2525    StyleParse = 1,
2526    /// The style's request failed, such as with a 404 or a missing file.
2527    StyleLoad = 2,
2528} Unrecognized
2529}
2530impl Default for MapLoadError {
2531    fn default() -> Self {
2532        Self::Unknown
2533    }
2534}
2535
2536native_enum! {
2537/// When a map renders.
2538///
2539/// See `mln_map_mode` in the
2540/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2541pub enum MapMode: u32 {
2542    /// Renders whenever the map changes.
2543    Continuous = 0,
2544    /// Renders only when `MapHandle::request_still_image()` asks for an image.
2545    Static = 1,
2546    /// Renders still images of single tiles, as `MapMode::Static` does.
2547    Tile = 2,
2548} Unknown
2549}
2550impl Default for MapMode {
2551    fn default() -> Self {
2552        Self::Continuous
2553    }
2554}
2555
2556/// Options for `RuntimeHandle::create_map()`.
2557///
2558/// See `mln_map_options` in the
2559/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2560#[derive(Debug, Clone, Copy, PartialEq)]
2561pub struct MapOptions {
2562    /// The map's first size, and its scale factor. The scale factor stays fixed
2563    /// for the map's life, and every render session of the map renders at it.
2564    pub initial_extent: LogicalExtent,
2565    pub map_mode: MapMode,
2566    /// Whether the map decodes MapLibre Tiles (MLT) that use FastPFOR integer
2567    /// encoding. Without it, such tiles fail to load.
2568    pub fast_pfor_enabled: bool,
2569    /// The events that the map reports. Without it, the map reports them all.
2570    pub event_mask: Option<RuntimeEventFlag>,
2571    /// Whether the map keeps tiles in memory after they leave the view, so they
2572    /// show again without loading. Without it, the map keeps them.
2573    pub tile_cache_enabled: Option<bool>,
2574}
2575impl MapOptions {
2576    pub fn new(initial_extent: LogicalExtent) -> Self {
2577        Self {
2578            initial_extent,
2579            map_mode: Default::default(),
2580            fast_pfor_enabled: Default::default(),
2581            event_mask: None,
2582            tile_cache_enabled: None,
2583        }
2584    }
2585}
2586impl ToNative<sys::mln_map_options> for MapOptions {
2587    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_map_options> {
2588        let mut raw: sys::mln_map_options = unsafe { std::mem::zeroed() };
2589        raw.size = std::mem::size_of::<sys::mln_map_options>() as _;
2590        raw.fields = 0;
2591        raw.initial_extent = to_native(&self.initial_extent, arena)?;
2592        raw.map_mode = to_native(&self.map_mode, arena)?;
2593        raw.fast_pfor_enabled = self.fast_pfor_enabled;
2594        if let Some(item) = &self.event_mask {
2595            raw.fields |= sys::MLN_MAP_OPTION_EVENT_MASK;
2596            raw.event_mask = to_native(&*item, arena)?;
2597        }
2598        if let Some(item) = &self.tile_cache_enabled {
2599            raw.fields |= sys::MLN_MAP_OPTION_TILE_CACHE_ENABLED;
2600            raw.tile_cache_enabled = *item;
2601        }
2602        Ok(raw)
2603    }
2604}
2605
2606/// A projection's camera, as `MapProjectionHandle::get_camera()` reports it.
2607///
2608/// See `mln_map_projection_camera_result` in the
2609/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/projection_8h.html).
2610#[derive(Debug, Clone, Copy, PartialEq, Default)]
2611pub struct MapProjectionCameraResult {
2612    pub camera: Camera,
2613}
2614impl FromNative<sys::mln_map_projection_camera_result> for MapProjectionCameraResult {
2615    unsafe fn from_native(raw: sys::mln_map_projection_camera_result) -> Result<Self> {
2616        Ok(Self {
2617            camera: unsafe { from_native(raw.camera) }?,
2618        })
2619    }
2620}
2621
2622/// A map's state, as `MapHandle::get_snapshot()` reads it.
2623///
2624/// See `mln_map_snapshot` in the
2625/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2626#[derive(Debug, Clone, Copy, PartialEq, Default)]
2627pub struct MapSnapshot {
2628    pub debug_flags: MapDebugFlag,
2629    /// Grows with each change to the map's state.
2630    pub generation: u64,
2631    /// Whether the style and every resource that the view needs have loaded.
2632    pub fully_loaded: bool,
2633    pub rendering_stats_view_enabled: bool,
2634    pub gesture_in_progress: bool,
2635    pub transition_in_progress: bool,
2636    pub event_mask: RuntimeEventFlag,
2637    /// Counts the render updates that the map has made for its render session.
2638    pub latest_render_update_generation: u64,
2639    pub tile: MapTileSettings,
2640    pub bounds: CameraBounds,
2641    pub free_camera: FreeCamera,
2642    pub view: MapView,
2643}
2644impl FromNative<sys::mln_map_snapshot> for MapSnapshot {
2645    unsafe fn from_native(raw: sys::mln_map_snapshot) -> Result<Self> {
2646        Ok(Self {
2647            debug_flags: MapDebugFlag::from_bits_retain(raw.debug_flags),
2648            generation: raw.generation,
2649            fully_loaded: raw.fully_loaded,
2650            rendering_stats_view_enabled: raw.rendering_stats_view_enabled,
2651            gesture_in_progress: raw.gesture_in_progress,
2652            transition_in_progress: raw.transition_in_progress,
2653            event_mask: RuntimeEventFlag::from_bits_retain(raw.event_mask),
2654            latest_render_update_generation: raw.latest_render_update_generation,
2655            tile: unsafe { from_native(raw.tile) }?,
2656            bounds: unsafe { from_native(raw.bounds) }?,
2657            free_camera: unsafe { from_native(raw.free_camera) }?,
2658            view: unsafe { from_native(raw.view) }?,
2659        })
2660    }
2661}
2662
2663/// How the map picks the tiles to load.
2664///
2665/// The `lod_` members lower the level of detail away from the camera, so the
2666/// map loads fewer tiles when the pitch is high.
2667///
2668/// See `mln_map_tile_options` in the
2669/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2670#[derive(Debug, Clone, Copy, PartialEq, Default)]
2671pub struct MapTileOptions {
2672    /// How many zoom levels lower the map also loads tiles for, so it can show
2673    /// a coarse map while the current tiles load. 0 loads only the current
2674    /// tiles.
2675    pub prefetch_zoom_delta: Option<u32>,
2676    /// The radius around the view point, in tiles, that keeps full detail.
2677    pub lod_min_radius: Option<f64>,
2678    /// Scales the distance to the view point. Above 1 lowers the detail.
2679    pub lod_scale: Option<f64>,
2680    /// The pitch, in degrees, above which the map lowers the detail.
2681    pub lod_pitch_threshold: Option<f64>,
2682    /// Zoom levels to add for picking the detail. Below 0 loads fewer tiles.
2683    pub lod_zoom_shift: Option<f64>,
2684    /// `TileLodMode::Distance` ignores `lod_min_radius`.
2685    pub lod_mode: Option<TileLodMode>,
2686}
2687impl ToNative<sys::mln_map_tile_options> for MapTileOptions {
2688    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_map_tile_options> {
2689        let mut raw: sys::mln_map_tile_options = unsafe { std::mem::zeroed() };
2690        raw.size = std::mem::size_of::<sys::mln_map_tile_options>() as _;
2691        raw.fields = 0;
2692        if let Some(item) = &self.prefetch_zoom_delta {
2693            raw.fields |= sys::MLN_MAP_TILE_OPTION_PREFETCH_ZOOM_DELTA;
2694            raw.prefetch_zoom_delta = *item;
2695        }
2696        if let Some(item) = &self.lod_min_radius {
2697            raw.fields |= sys::MLN_MAP_TILE_OPTION_LOD_MIN_RADIUS;
2698            raw.lod_min_radius = *item;
2699        }
2700        if let Some(item) = &self.lod_scale {
2701            raw.fields |= sys::MLN_MAP_TILE_OPTION_LOD_SCALE;
2702            raw.lod_scale = *item;
2703        }
2704        if let Some(item) = &self.lod_pitch_threshold {
2705            raw.fields |= sys::MLN_MAP_TILE_OPTION_LOD_PITCH_THRESHOLD;
2706            raw.lod_pitch_threshold = *item;
2707        }
2708        if let Some(item) = &self.lod_zoom_shift {
2709            raw.fields |= sys::MLN_MAP_TILE_OPTION_LOD_ZOOM_SHIFT;
2710            raw.lod_zoom_shift = *item;
2711        }
2712        if let Some(item) = &self.lod_mode {
2713            raw.fields |= sys::MLN_MAP_TILE_OPTION_LOD_MODE;
2714            raw.lod_mode = to_native(&*item, arena)?;
2715        }
2716        Ok(raw)
2717    }
2718}
2719
2720/// All the settings for how a map picks the tiles to load.
2721///
2722/// Its members mean the same as those of `MapTileOptions`.
2723///
2724/// See `mln_map_tile_settings` in the
2725/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2726#[derive(Debug, Clone, Copy, PartialEq, Default)]
2727pub struct MapTileSettings {
2728    pub prefetch_zoom_delta: u32,
2729    pub lod_min_radius: f64,
2730    pub lod_scale: f64,
2731    /// The pitch, in degrees, above which the map lowers the detail.
2732    pub lod_pitch_threshold: f64,
2733    pub lod_zoom_shift: f64,
2734    pub lod_mode: TileLodMode,
2735}
2736impl FromNative<sys::mln_map_tile_settings> for MapTileSettings {
2737    unsafe fn from_native(raw: sys::mln_map_tile_settings) -> Result<Self> {
2738        Ok(Self {
2739            prefetch_zoom_delta: raw.prefetch_zoom_delta,
2740            lod_min_radius: raw.lod_min_radius,
2741            lod_scale: raw.lod_scale,
2742            lod_pitch_threshold: raw.lod_pitch_threshold,
2743            lod_zoom_shift: raw.lod_zoom_shift,
2744            lod_mode: TileLodMode::from_raw(raw.lod_mode),
2745        })
2746    }
2747}
2748
2749/// One view of a map: its camera, size, and projection.
2750///
2751/// See `mln_map_view` in the
2752/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2753#[derive(Debug, Clone, Copy, PartialEq, Default)]
2754pub struct MapView {
2755    pub camera: Camera,
2756    pub extent: LogicalExtent,
2757    pub projection_mode: ProjectionMode,
2758    pub viewport: MapViewport,
2759}
2760impl ToNative<sys::mln_map_view> for MapView {
2761    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_map_view> {
2762        let mut raw: sys::mln_map_view = unsafe { std::mem::zeroed() };
2763        raw.size = std::mem::size_of::<sys::mln_map_view>() as _;
2764        raw.camera = to_native(&self.camera, arena)?;
2765        raw.extent = to_native(&self.extent, arena)?;
2766        raw.projection_mode = to_native(&self.projection_mode, arena)?;
2767        raw.viewport = to_native(&self.viewport, arena)?;
2768        Ok(raw)
2769    }
2770}
2771impl FromNative<sys::mln_map_view> for MapView {
2772    unsafe fn from_native(raw: sys::mln_map_view) -> Result<Self> {
2773        Ok(Self {
2774            camera: unsafe { from_native(raw.camera) }?,
2775            extent: unsafe { from_native(raw.extent) }?,
2776            projection_mode: unsafe { from_native(raw.projection_mode) }?,
2777            viewport: unsafe { from_native(raw.viewport) }?,
2778        })
2779    }
2780}
2781
2782/// A map's whole viewport.
2783///
2784/// Its members mean the same as those of `MapViewportOptions`.
2785///
2786/// See `mln_map_viewport` in the
2787/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2788#[derive(Debug, Clone, Copy, PartialEq, Default)]
2789pub struct MapViewport {
2790    pub north_orientation: NorthOrientation,
2791    pub constrain_mode: ConstrainMode,
2792    pub viewport_mode: ViewportMode,
2793    pub frustum_offset: EdgeInsets,
2794}
2795impl ToNative<sys::mln_map_viewport> for MapViewport {
2796    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_map_viewport> {
2797        let mut raw: sys::mln_map_viewport = unsafe { std::mem::zeroed() };
2798        raw.north_orientation = to_native(&self.north_orientation, arena)?;
2799        raw.constrain_mode = to_native(&self.constrain_mode, arena)?;
2800        raw.viewport_mode = to_native(&self.viewport_mode, arena)?;
2801        raw.frustum_offset = to_native(&self.frustum_offset, arena)?;
2802        Ok(raw)
2803    }
2804}
2805impl FromNative<sys::mln_map_viewport> for MapViewport {
2806    unsafe fn from_native(raw: sys::mln_map_viewport) -> Result<Self> {
2807        Ok(Self {
2808            north_orientation: NorthOrientation::from_raw(raw.north_orientation),
2809            constrain_mode: ConstrainMode::from_raw(raw.constrain_mode),
2810            viewport_mode: ViewportMode::from_raw(raw.viewport_mode),
2811            frustum_offset: unsafe { from_native(raw.frustum_offset) }?,
2812        })
2813    }
2814}
2815
2816/// How the map orients and constrains its view.
2817///
2818/// See `mln_map_viewport_options` in the
2819/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
2820#[derive(Debug, Clone, Copy, PartialEq, Default)]
2821pub struct MapViewportOptions {
2822    pub north_orientation: Option<NorthOrientation>,
2823    pub constrain_mode: Option<ConstrainMode>,
2824    pub viewport_mode: Option<ViewportMode>,
2825    pub frustum_offset: Option<EdgeInsets>,
2826}
2827impl ToNative<sys::mln_map_viewport_options> for MapViewportOptions {
2828    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_map_viewport_options> {
2829        let mut raw: sys::mln_map_viewport_options = unsafe { std::mem::zeroed() };
2830        raw.size = std::mem::size_of::<sys::mln_map_viewport_options>() as _;
2831        raw.fields = 0;
2832        if let Some(item) = &self.north_orientation {
2833            raw.fields |= sys::MLN_MAP_VIEWPORT_OPTION_NORTH_ORIENTATION;
2834            raw.north_orientation = to_native(&*item, arena)?;
2835        }
2836        if let Some(item) = &self.constrain_mode {
2837            raw.fields |= sys::MLN_MAP_VIEWPORT_OPTION_CONSTRAIN_MODE;
2838            raw.constrain_mode = to_native(&*item, arena)?;
2839        }
2840        if let Some(item) = &self.viewport_mode {
2841            raw.fields |= sys::MLN_MAP_VIEWPORT_OPTION_VIEWPORT_MODE;
2842            raw.viewport_mode = to_native(&*item, arena)?;
2843        }
2844        if let Some(item) = &self.frustum_offset {
2845            raw.fields |= sys::MLN_MAP_VIEWPORT_OPTION_FRUSTUM_OFFSET;
2846            raw.frustum_offset = to_native(&*item, arena)?;
2847        }
2848        Ok(raw)
2849    }
2850}
2851
2852/// A Metal texture of a borrowed ring.
2853///
2854/// See `mln_metal_borrowed_texture` in the
2855/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
2856#[derive(Debug, Clone, Copy, PartialEq)]
2857pub struct MetalBorrowedTexture {
2858    /// Your MTLTexture.
2859    pub texture: *mut std::ffi::c_void,
2860}
2861impl MetalBorrowedTexture {
2862    pub fn new(texture: *mut std::ffi::c_void) -> Self {
2863        Self { texture }
2864    }
2865}
2866impl ToNative<sys::mln_metal_borrowed_texture> for MetalBorrowedTexture {
2867    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_metal_borrowed_texture> {
2868        let mut raw: sys::mln_metal_borrowed_texture = unsafe { std::mem::zeroed() };
2869        raw.texture = self.texture;
2870        Ok(raw)
2871    }
2872}
2873
2874/// A ring of your Metal textures, for
2875/// `MapHandle::attach_metal_borrowed_texture()`.
2876///
2877/// `logical_size` sets the map's size. `physical_width` and `physical_height`
2878/// give the textures' size in pixels, which is usually `logical_size` times the
2879/// map's scale factor. The textures must all have that size, one device, one
2880/// pixel format, one sample, and MTLTextureUsageRenderTarget. The ring holds up
2881/// to `TEXTURE_RING_MAX_DEPTH` distinct textures.
2882///
2883/// The session uses the textures until a replacement or release of the target
2884/// completes, a detach or release of the session completes, or an abandon of it
2885/// returns.
2886///
2887/// See `mln_metal_borrowed_texture_descriptor` in the
2888/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
2889#[derive(Debug, Clone, PartialEq)]
2890pub struct MetalBorrowedTextureDescriptor {
2891    pub logical_size: LogicalSize,
2892    pub physical_width: u32,
2893    pub physical_height: u32,
2894    pub textures: Vec<MetalBorrowedTexture>,
2895    /// Your MTLCommandQueue on the textures' device, or null for a queue of the
2896    /// session's own. With your queue, frames can use
2897    /// `GpuSyncKind::QueueOrder`.
2898    pub command_queue: *mut std::ffi::c_void,
2899}
2900impl MetalBorrowedTextureDescriptor {
2901    pub fn new(
2902        logical_size: LogicalSize,
2903        physical_width: u32,
2904        physical_height: u32,
2905        textures: Vec<MetalBorrowedTexture>,
2906    ) -> Self {
2907        Self {
2908            logical_size,
2909            physical_width,
2910            physical_height,
2911            textures,
2912            command_queue: Default::default(),
2913        }
2914    }
2915}
2916impl ToNative<sys::mln_metal_borrowed_texture_descriptor> for MetalBorrowedTextureDescriptor {
2917    fn to_native(
2918        &self,
2919        arena: &mut InputArena,
2920    ) -> Result<sys::mln_metal_borrowed_texture_descriptor> {
2921        let mut raw: sys::mln_metal_borrowed_texture_descriptor = unsafe { std::mem::zeroed() };
2922        raw.size = std::mem::size_of::<sys::mln_metal_borrowed_texture_descriptor>() as _;
2923        raw.logical_size = to_native(&self.logical_size, arena)?;
2924        raw.physical_width = self.physical_width;
2925        raw.physical_height = self.physical_height;
2926        raw.textures = convert::array(&self.textures, arena)?;
2927        raw.texture_count = convert::count(self.textures.len())?;
2928        raw.command_queue = self.command_queue;
2929        Ok(raw)
2930    }
2931}
2932
2933/// New Metal textures for a borrowed ring, for
2934/// `RenderSessionHandle::set_metal_borrowed_texture_target()`.
2935///
2936/// The members and the textures follow the rules of
2937/// `MetalBorrowedTextureDescriptor`. The ring keeps its depth, device, and
2938/// command queue, so give it as many textures as it attached with, on the same
2939/// device.
2940///
2941/// See `mln_metal_borrowed_texture_replacement` in the
2942/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
2943#[derive(Debug, Clone, PartialEq)]
2944pub struct MetalBorrowedTextureReplacement {
2945    pub logical_size: LogicalSize,
2946    pub physical_width: u32,
2947    pub physical_height: u32,
2948    pub textures: Vec<MetalBorrowedTexture>,
2949}
2950impl MetalBorrowedTextureReplacement {
2951    pub fn new(
2952        logical_size: LogicalSize,
2953        physical_width: u32,
2954        physical_height: u32,
2955        textures: Vec<MetalBorrowedTexture>,
2956    ) -> Self {
2957        Self {
2958            logical_size,
2959            physical_width,
2960            physical_height,
2961            textures,
2962        }
2963    }
2964}
2965impl ToNative<sys::mln_metal_borrowed_texture_replacement> for MetalBorrowedTextureReplacement {
2966    fn to_native(
2967        &self,
2968        arena: &mut InputArena,
2969    ) -> Result<sys::mln_metal_borrowed_texture_replacement> {
2970        let mut raw: sys::mln_metal_borrowed_texture_replacement = unsafe { std::mem::zeroed() };
2971        raw.size = std::mem::size_of::<sys::mln_metal_borrowed_texture_replacement>() as _;
2972        raw.logical_size = to_native(&self.logical_size, arena)?;
2973        raw.physical_width = self.physical_width;
2974        raw.physical_height = self.physical_height;
2975        raw.textures = convert::array(&self.textures, arena)?;
2976        raw.texture_count = convert::count(self.textures.len())?;
2977        Ok(raw)
2978    }
2979}
2980
2981/// The Metal device that a render session uses.
2982///
2983/// See `mln_metal_context_descriptor` in the
2984/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
2985#[derive(Debug, Clone, Copy, PartialEq, Default)]
2986pub struct MetalContextDescriptor {
2987    /// An `MTLDevice`.
2988    pub device: *mut std::ffi::c_void,
2989}
2990impl ToNative<sys::mln_metal_context_descriptor> for MetalContextDescriptor {
2991    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_metal_context_descriptor> {
2992        let mut raw: sys::mln_metal_context_descriptor = unsafe { std::mem::zeroed() };
2993        raw.device = self.device;
2994        Ok(raw)
2995    }
2996}
2997
2998/// A Metal layer to render to, for `MapHandle::attach_metal_surface()`.
2999///
3000/// The session sets the layer's device, pixel format, and drawable size. It
3001/// uses the layer until a replacement or release of the target completes, a
3002/// detach or release of the session completes, or an abandon of it returns.
3003///
3004/// See `mln_metal_surface_descriptor` in the
3005/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
3006#[derive(Debug, Clone, Copy, PartialEq)]
3007pub struct MetalSurfaceDescriptor {
3008    pub logical_size: LogicalSize,
3009    /// The MTLDevice to render with. A null device picks the system's default.
3010    pub context: MetalContextDescriptor,
3011    /// Your CAMetalLayer.
3012    pub layer: *mut std::ffi::c_void,
3013}
3014impl MetalSurfaceDescriptor {
3015    pub fn new(logical_size: LogicalSize, layer: *mut std::ffi::c_void) -> Self {
3016        Self {
3017            logical_size,
3018            context: Default::default(),
3019            layer,
3020        }
3021    }
3022}
3023impl ToNative<sys::mln_metal_surface_descriptor> for MetalSurfaceDescriptor {
3024    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_metal_surface_descriptor> {
3025        let mut raw: sys::mln_metal_surface_descriptor = unsafe { std::mem::zeroed() };
3026        raw.size = std::mem::size_of::<sys::mln_metal_surface_descriptor>() as _;
3027        raw.logical_size = to_native(&self.logical_size, arena)?;
3028        raw.context = to_native(&self.context, arena)?;
3029        raw.layer = self.layer;
3030        Ok(raw)
3031    }
3032}
3033
3034/// A new Metal layer for `RenderSessionHandle::set_metal_surface_target()`.
3035///
3036/// The session renders to it with the device that it attached with. It uses the
3037/// layer until a replacement or release of the target completes, a detach or
3038/// release of the session completes, or an abandon of it returns.
3039///
3040/// See `mln_metal_surface_replacement` in the
3041/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
3042#[derive(Debug, Clone, Copy, PartialEq)]
3043pub struct MetalSurfaceReplacement {
3044    pub logical_size: LogicalSize,
3045    /// Your CAMetalLayer.
3046    pub layer: *mut std::ffi::c_void,
3047}
3048impl MetalSurfaceReplacement {
3049    pub fn new(logical_size: LogicalSize, layer: *mut std::ffi::c_void) -> Self {
3050        Self {
3051            logical_size,
3052            layer,
3053        }
3054    }
3055}
3056impl ToNative<sys::mln_metal_surface_replacement> for MetalSurfaceReplacement {
3057    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_metal_surface_replacement> {
3058        let mut raw: sys::mln_metal_surface_replacement = unsafe { std::mem::zeroed() };
3059        raw.size = std::mem::size_of::<sys::mln_metal_surface_replacement>() as _;
3060        raw.logical_size = to_native(&self.logical_size, arena)?;
3061        raw.layer = self.layer;
3062        Ok(raw)
3063    }
3064}
3065
3066/// The Metal texture of an acquired frame.
3067///
3068/// See `mln_metal_texture_frame` in the
3069/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
3070#[derive(Debug, Clone, Copy, PartialEq, Default)]
3071pub struct MetalTextureFrame {
3072    pub width: u32,
3073    pub height: u32,
3074    pub scale_factor: f64,
3075    /// The texture's index in the descriptor's `textures`.
3076    pub slot: u32,
3077    /// The MTLTexture.
3078    pub texture: *mut std::ffi::c_void,
3079    /// The texture's MTLDevice.
3080    pub device: *mut std::ffi::c_void,
3081    /// The texture's MTLPixelFormat.
3082    pub pixel_format: u64,
3083}
3084impl FromNative<sys::mln_metal_texture_frame> for MetalTextureFrame {
3085    unsafe fn from_native(raw: sys::mln_metal_texture_frame) -> Result<Self> {
3086        Ok(Self {
3087            width: raw.width,
3088            height: raw.height,
3089            scale_factor: raw.scale_factor,
3090            slot: raw.slot,
3091            texture: raw.texture,
3092            device: raw.device,
3093            pixel_format: raw.pixel_format,
3094        })
3095    }
3096}
3097
3098/// How one part of a gesture's momentum slows from its release speed.
3099///
3100/// Speeds and distances are in the part's unit: logical pixels for pan, zoom
3101/// levels for zoom, and degrees for bearing and pitch. A setting whose bit
3102/// isn't set takes the part's default, which `GestureMomentum` lists.
3103/// `min_speed` is finite and not negative, and every other number is finite and
3104/// positive. A friction decay can serve every release, as a preset that matches
3105/// a platform's scrolling. An eased glide takes its direction from the part's
3106/// velocity, and its distance and duration from the caller's plan.
3107///
3108/// See `mln_momentum_decay` in the
3109/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3110#[derive(Debug, Clone, Copy, PartialEq, Default)]
3111pub struct MomentumDecay {
3112    pub model: Option<MomentumDecayModel>,
3113    /// For `MomentumDecayModel::Friction`, how long the speed takes to halve.
3114    pub half_life_ms: Option<f64>,
3115    /// For `MomentumDecayModel::Friction`, the speed at which it ends.
3116    pub stop_speed: Option<f64>,
3117    /// Required for `MomentumDecayModel::Ease`.
3118    pub distance: Option<f64>,
3119    /// Required for `MomentumDecayModel::Ease`.
3120    pub duration_ms: Option<f64>,
3121    /// For `MomentumDecayModel::Ease`, the share of `distance` covered over the
3122    /// share of `duration_ms`. Its control points are between 0 and 1, so the
3123    /// glide never passes its distance. Defaults to (0, 0, 0.25, 1), the curve
3124    /// that camera animations ease along by default. Android's scroll fling
3125    /// follows (0.175, 0.5, 0.35, 1).
3126    pub easing: Option<UnitBezier>,
3127    /// A slower release starts no momentum.
3128    pub min_speed: Option<f64>,
3129    /// For `MomentumDecayModel::Friction`, a faster release counts as this.
3130    pub max_speed: Option<f64>,
3131    /// The farthest the part moves. A friction release that would move farther
3132    /// starts slower, so it ends sooner, and a planned glide moves at most this
3133    /// far over its duration.
3134    pub max_distance: Option<f64>,
3135}
3136impl ToNative<sys::mln_momentum_decay> for MomentumDecay {
3137    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_momentum_decay> {
3138        let mut raw: sys::mln_momentum_decay = unsafe { std::mem::zeroed() };
3139        raw.fields = 0;
3140        if let Some(item) = &self.model {
3141            raw.fields |= sys::MLN_MOMENTUM_DECAY_MODEL;
3142            raw.model = to_native(&*item, arena)?;
3143        }
3144        if let Some(item) = &self.half_life_ms {
3145            raw.fields |= sys::MLN_MOMENTUM_DECAY_HALF_LIFE_MS;
3146            raw.half_life_ms = *item;
3147        }
3148        if let Some(item) = &self.stop_speed {
3149            raw.fields |= sys::MLN_MOMENTUM_DECAY_STOP_SPEED;
3150            raw.stop_speed = *item;
3151        }
3152        if let Some(item) = &self.distance {
3153            raw.fields |= sys::MLN_MOMENTUM_DECAY_DISTANCE;
3154            raw.distance = *item;
3155        }
3156        if let Some(item) = &self.duration_ms {
3157            raw.fields |= sys::MLN_MOMENTUM_DECAY_DURATION_MS;
3158            raw.duration_ms = *item;
3159        }
3160        if let Some(item) = &self.easing {
3161            raw.fields |= sys::MLN_MOMENTUM_DECAY_EASING;
3162            raw.easing = to_native(&*item, arena)?;
3163        }
3164        if let Some(item) = &self.min_speed {
3165            raw.fields |= sys::MLN_MOMENTUM_DECAY_MIN_SPEED;
3166            raw.min_speed = *item;
3167        }
3168        if let Some(item) = &self.max_speed {
3169            raw.fields |= sys::MLN_MOMENTUM_DECAY_MAX_SPEED;
3170            raw.max_speed = *item;
3171        }
3172        if let Some(item) = &self.max_distance {
3173            raw.fields |= sys::MLN_MOMENTUM_DECAY_MAX_DISTANCE;
3174            raw.max_distance = *item;
3175        }
3176        Ok(raw)
3177    }
3178}
3179
3180native_enum! {
3181/// How a part of a gesture's momentum slows from its release speed.
3182///
3183/// See `mln_momentum_decay_model` in the
3184/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3185pub enum MomentumDecayModel: u32 {
3186    /// The speed halves every `half_life_ms`, until it drops to `stop_speed`.
3187    /// UIScrollView's normal deceleration is a half-life of 346 ms, and its
3188    /// fast deceleration 69 ms.
3189    Friction = 0,
3190    /// The part eases `distance` over `duration_ms`, along `easing`, as a
3191    /// camera animation does. The caller plans the glide, for example from the
3192    /// platform's own fling physics, such as Android's OverScroller.
3193    Ease = 1,
3194} Unknown
3195}
3196impl Default for MomentumDecayModel {
3197    fn default() -> Self {
3198        Self::Friction
3199    }
3200}
3201
3202/// Where a part settles after a gesture that changed it.
3203///
3204/// The targets are every `spacing` from `offset`, in the part's unit. Bearing
3205/// targets wrap around the circle. Once the part's glide ends, or right away
3206/// when it doesn't move, the part eases to the nearest target if it is within
3207/// `tolerance` of it, and otherwise stays where it is. A setting whose bit
3208/// isn't set takes the part's default, which `GestureMomentum` lists.
3209///
3210/// See `mln_momentum_snap` in the
3211/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3212#[derive(Debug, Clone, Copy, PartialEq, Default)]
3213pub struct MomentumSnap {
3214    /// Positive.
3215    pub spacing: Option<f64>,
3216    /// Defaults to 0.
3217    pub offset: Option<f64>,
3218    /// Not negative.
3219    pub tolerance: Option<f64>,
3220    /// Zero settles without easing. Defaults to 300.
3221    pub duration_ms: Option<f64>,
3222}
3223impl ToNative<sys::mln_momentum_snap> for MomentumSnap {
3224    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_momentum_snap> {
3225        let mut raw: sys::mln_momentum_snap = unsafe { std::mem::zeroed() };
3226        raw.fields = 0;
3227        if let Some(item) = &self.spacing {
3228            raw.fields |= sys::MLN_MOMENTUM_SNAP_SPACING;
3229            raw.spacing = *item;
3230        }
3231        if let Some(item) = &self.offset {
3232            raw.fields |= sys::MLN_MOMENTUM_SNAP_OFFSET;
3233            raw.offset = *item;
3234        }
3235        if let Some(item) = &self.tolerance {
3236            raw.fields |= sys::MLN_MOMENTUM_SNAP_TOLERANCE;
3237            raw.tolerance = *item;
3238        }
3239        if let Some(item) = &self.duration_ms {
3240            raw.fields |= sys::MLN_MOMENTUM_SNAP_DURATION_MS;
3241            raw.duration_ms = *item;
3242        }
3243        Ok(raw)
3244    }
3245}
3246
3247native_enum! {
3248/// Whether the library may use the network.
3249///
3250/// See `mln_network_status` in the
3251/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
3252pub enum NetworkStatus: u32 {
3253    Online = 1,
3254    Offline = 2,
3255} Unknown
3256}
3257
3258native_enum! {
3259/// The screen direction that north points to when the bearing is 0.
3260///
3261/// See `mln_north_orientation` in the
3262/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3263pub enum NorthOrientation: u32 {
3264    Up = 0,
3265    Right = 1,
3266    Down = 2,
3267    Left = 3,
3268} Unknown
3269}
3270impl Default for NorthOrientation {
3271    fn default() -> Self {
3272        Self::Up
3273    }
3274}
3275
3276/// An offline region that covers a GeoJSON geometry.
3277///
3278/// The members other than `geometry` mean the same as those of
3279/// `OfflineTilePyramidRegionDefinition`.
3280///
3281/// See `mln_offline_geometry_region_definition` in the
3282/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3283#[derive(Debug, Clone, PartialEq)]
3284pub struct OfflineGeometryRegionDefinition {
3285    pub style_url: String,
3286    pub geometry: String,
3287    pub min_zoom: f64,
3288    pub max_zoom: f64,
3289    pub pixel_ratio: f32,
3290    pub include_ideographs: bool,
3291}
3292impl OfflineGeometryRegionDefinition {
3293    pub fn new(geometry: String) -> Self {
3294        Self {
3295            style_url: Default::default(),
3296            geometry,
3297            min_zoom: Default::default(),
3298            max_zoom: Default::default(),
3299            pixel_ratio: Default::default(),
3300            include_ideographs: Default::default(),
3301        }
3302    }
3303}
3304impl ToNative<sys::mln_offline_geometry_region_definition> for OfflineGeometryRegionDefinition {
3305    fn to_native(
3306        &self,
3307        arena: &mut InputArena,
3308    ) -> Result<sys::mln_offline_geometry_region_definition> {
3309        let mut raw: sys::mln_offline_geometry_region_definition = unsafe { std::mem::zeroed() };
3310        raw.style_url = to_native(&self.style_url, arena)?;
3311        raw.geometry = to_native(&self.geometry, arena)?;
3312        raw.min_zoom = self.min_zoom;
3313        raw.max_zoom = self.max_zoom;
3314        raw.pixel_ratio = self.pixel_ratio;
3315        raw.include_ideographs = self.include_ideographs;
3316        Ok(raw)
3317    }
3318}
3319impl FromNative<sys::mln_offline_geometry_region_definition> for OfflineGeometryRegionDefinition {
3320    unsafe fn from_native(raw: sys::mln_offline_geometry_region_definition) -> Result<Self> {
3321        Ok(Self {
3322            style_url: unsafe { from_native(raw.style_url) }?,
3323            geometry: unsafe { from_native(raw.geometry) }?,
3324            min_zoom: raw.min_zoom,
3325            max_zoom: raw.max_zoom,
3326            pixel_ratio: raw.pixel_ratio,
3327            include_ideographs: raw.include_ideographs,
3328        })
3329    }
3330}
3331
3332/// The area, zoom range, and style that an offline region covers.
3333///
3334/// See `mln_offline_region_definition` in the
3335/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3336#[derive(Debug, Clone, PartialEq)]
3337pub enum OfflineRegionDefinition {
3338    TilePyramid(OfflineTilePyramidRegionDefinition),
3339    Geometry(OfflineGeometryRegionDefinition),
3340    Unknown(u32),
3341}
3342impl Default for OfflineRegionDefinition {
3343    fn default() -> Self {
3344        Self::Unknown(0)
3345    }
3346}
3347impl ToNative<sys::mln_offline_region_definition> for OfflineRegionDefinition {
3348    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_offline_region_definition> {
3349        let mut raw: sys::mln_offline_region_definition = unsafe { std::mem::zeroed() };
3350        raw.size = std::mem::size_of::<sys::mln_offline_region_definition>() as _;
3351        match self {
3352            OfflineRegionDefinition::TilePyramid(item) => {
3353                raw.type_ = sys::MLN_OFFLINE_REGION_DEFINITION_TILE_PYRAMID;
3354                raw.data.tile_pyramid = to_native(&(*item), arena)?;
3355            }
3356            OfflineRegionDefinition::Geometry(item) => {
3357                raw.type_ = sys::MLN_OFFLINE_REGION_DEFINITION_GEOMETRY;
3358                raw.data.geometry = to_native(&(*item), arena)?;
3359            }
3360            OfflineRegionDefinition::Unknown(_) => {
3361                return Err(Error::invalid_argument(
3362                    "unknown union variant cannot be submitted",
3363                ));
3364            }
3365        }
3366        Ok(raw)
3367    }
3368}
3369impl FromNative<sys::mln_offline_region_definition> for OfflineRegionDefinition {
3370    unsafe fn from_native(raw: sys::mln_offline_region_definition) -> Result<Self> {
3371        Ok(match raw.type_ {
3372            sys::MLN_OFFLINE_REGION_DEFINITION_TILE_PYRAMID => {
3373                OfflineRegionDefinition::TilePyramid(unsafe { from_native(raw.data.tile_pyramid) }?)
3374            }
3375            sys::MLN_OFFLINE_REGION_DEFINITION_GEOMETRY => {
3376                OfflineRegionDefinition::Geometry(unsafe { from_native(raw.data.geometry) }?)
3377            }
3378            tag => OfflineRegionDefinition::Unknown(tag as u32),
3379        })
3380    }
3381}
3382
3383native_enum! {
3384/// Whether an offline region is downloading.
3385///
3386/// See `mln_offline_region_download_state` in the
3387/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
3388pub enum OfflineRegionDownloadState: u32 {
3389    Inactive = 0,
3390    Active = 1,
3391} Unknown
3392}
3393impl Default for OfflineRegionDownloadState {
3394    fn default() -> Self {
3395        Self::Inactive
3396    }
3397}
3398
3399/// An offline region in the runtime's cache file.
3400///
3401/// See `mln_offline_region_info` in the
3402/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3403#[derive(Debug, Clone, PartialEq, Default)]
3404pub struct OfflineRegionInfo {
3405    pub id: i64,
3406    pub definition: OfflineRegionDefinition,
3407    pub metadata: Vec<u8>,
3408}
3409impl FromNative<sys::mln_offline_region_info> for OfflineRegionInfo {
3410    unsafe fn from_native(raw: sys::mln_offline_region_info) -> Result<Self> {
3411        Ok(Self {
3412            id: raw.id,
3413            definition: unsafe { from_native(raw.definition) }?,
3414            metadata: unsafe { convert::counted(raw.metadata, raw.metadata_size) }?,
3415        })
3416    }
3417}
3418
3419/// The download progress of an offline region.
3420///
3421/// See `mln_offline_region_status` in the
3422/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
3423#[derive(Debug, Clone, Copy, PartialEq, Default)]
3424pub struct OfflineRegionStatus {
3425    pub download_state: OfflineRegionDownloadState,
3426    /// The resources downloaded so far, tiles included.
3427    pub completed_resource_count: u64,
3428    /// The size of the downloaded resources in bytes, tiles included.
3429    pub completed_resource_size: u64,
3430    pub completed_tile_count: u64,
3431    pub required_tile_count: u64,
3432    /// The size of the downloaded tiles in bytes.
3433    pub completed_tile_size: u64,
3434    /// The resources that the region needs, tiles included. Until
3435    /// `required_resource_count_is_precise` is true, this is only a lower
3436    /// bound.
3437    pub required_resource_count: u64,
3438    pub required_resource_count_is_precise: bool,
3439    /// Whether the region has downloaded every resource it needs.
3440    pub complete: bool,
3441}
3442impl FromNative<sys::mln_offline_region_status> for OfflineRegionStatus {
3443    unsafe fn from_native(raw: sys::mln_offline_region_status) -> Result<Self> {
3444        Ok(Self {
3445            download_state: OfflineRegionDownloadState::from_raw(raw.download_state),
3446            completed_resource_count: raw.completed_resource_count,
3447            completed_resource_size: raw.completed_resource_size,
3448            completed_tile_count: raw.completed_tile_count,
3449            required_tile_count: raw.required_tile_count,
3450            completed_tile_size: raw.completed_tile_size,
3451            required_resource_count: raw.required_resource_count,
3452            required_resource_count_is_precise: raw.required_resource_count_is_precise,
3453            complete: raw.complete,
3454        })
3455    }
3456}
3457
3458/// An offline region that covers a rectangle of the map.
3459///
3460/// See `mln_offline_tile_pyramid_region_definition` in the
3461/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3462#[derive(Debug, Clone, PartialEq, Default)]
3463pub struct OfflineTilePyramidRegionDefinition {
3464    /// The style whose resources the region holds. Maps use the region when
3465    /// they load the same style URL.
3466    pub style_url: String,
3467    pub bounds: LatLngBounds,
3468    pub min_zoom: f64,
3469    /// INFINITY covers every zoom level that the style's sources have.
3470    pub max_zoom: f64,
3471    /// The pixel ratio of the images to download, such as 2 for dense screens.
3472    pub pixel_ratio: f32,
3473    /// Whether the region holds the glyphs of CJK ideographs.
3474    pub include_ideographs: bool,
3475}
3476impl ToNative<sys::mln_offline_tile_pyramid_region_definition>
3477    for OfflineTilePyramidRegionDefinition
3478{
3479    fn to_native(
3480        &self,
3481        arena: &mut InputArena,
3482    ) -> Result<sys::mln_offline_tile_pyramid_region_definition> {
3483        let mut raw: sys::mln_offline_tile_pyramid_region_definition =
3484            unsafe { std::mem::zeroed() };
3485        raw.style_url = to_native(&self.style_url, arena)?;
3486        raw.bounds = to_native(&self.bounds, arena)?;
3487        raw.min_zoom = self.min_zoom;
3488        raw.max_zoom = self.max_zoom;
3489        raw.pixel_ratio = self.pixel_ratio;
3490        raw.include_ideographs = self.include_ideographs;
3491        Ok(raw)
3492    }
3493}
3494impl FromNative<sys::mln_offline_tile_pyramid_region_definition>
3495    for OfflineTilePyramidRegionDefinition
3496{
3497    unsafe fn from_native(raw: sys::mln_offline_tile_pyramid_region_definition) -> Result<Self> {
3498        Ok(Self {
3499            style_url: unsafe { from_native(raw.style_url) }?,
3500            bounds: unsafe { from_native(raw.bounds) }?,
3501            min_zoom: raw.min_zoom,
3502            max_zoom: raw.max_zoom,
3503            pixel_ratio: raw.pixel_ratio,
3504            include_ideographs: raw.include_ideographs,
3505        })
3506    }
3507}
3508
3509/// The image that `MapHandle::attach_offscreen()` renders. The session renders
3510/// it at the map's scale factor.
3511///
3512/// See `mln_offscreen_descriptor` in the
3513/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/offscreen_8h.html).
3514#[derive(Debug, Clone, Copy, PartialEq)]
3515pub struct OffscreenDescriptor {
3516    pub logical_size: LogicalSize,
3517}
3518impl OffscreenDescriptor {
3519    pub const fn new(logical_size: LogicalSize) -> Self {
3520        Self { logical_size }
3521    }
3522}
3523impl ToNative<sys::mln_offscreen_descriptor> for OffscreenDescriptor {
3524    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_offscreen_descriptor> {
3525        let mut raw: sys::mln_offscreen_descriptor = unsafe { std::mem::zeroed() };
3526        raw.size = std::mem::size_of::<sys::mln_offscreen_descriptor>() as _;
3527        raw.logical_size = to_native(&self.logical_size, arena)?;
3528        Ok(raw)
3529    }
3530}
3531
3532/// Options for `OffscreenDeviceHandle::create()`.
3533///
3534/// See `mln_offscreen_device_options` in the
3535/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/offscreen_8h.html).
3536#[derive(Debug, Clone, Copy, PartialEq, Default)]
3537pub struct OffscreenDeviceOptions {
3538    /// The GPU to use, as an index into the platform's list of GPUs.
3539    pub adapter_index: Option<u32>,
3540    /// Whether the device's sessions take turns in one OpenGL context instead
3541    /// of having one each. Only an EGL device reads it.
3542    pub single_context: Option<bool>,
3543    /// The OpenGL API that the device's sessions render with. An EGL device
3544    /// defaults to `OpenGlClientApi::Gles`, and takes `OpenGlClientApi::Gl` too
3545    /// on Linux and FreeBSD. A WGL device takes only `OpenGlClientApi::Gl`, its
3546    /// default, and a WebGL device only `OpenGlClientApi::Gles`, its default.
3547    /// Other devices take neither.
3548    pub client_api: Option<OpenGlClientApi>,
3549}
3550impl ToNative<sys::mln_offscreen_device_options> for OffscreenDeviceOptions {
3551    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_offscreen_device_options> {
3552        let mut raw: sys::mln_offscreen_device_options = unsafe { std::mem::zeroed() };
3553        raw.size = std::mem::size_of::<sys::mln_offscreen_device_options>() as _;
3554        raw.fields = 0;
3555        if let Some(item) = &self.adapter_index {
3556            raw.fields |= sys::MLN_OFFSCREEN_DEVICE_OPTION_ADAPTER_INDEX;
3557            raw.adapter_index = *item;
3558        }
3559        if let Some(item) = &self.single_context {
3560            raw.fields |= sys::MLN_OFFSCREEN_DEVICE_OPTION_SINGLE_CONTEXT;
3561            raw.single_context = *item;
3562        }
3563        if let Some(item) = &self.client_api {
3564            raw.fields |= sys::MLN_OFFSCREEN_DEVICE_OPTION_CLIENT_API;
3565            raw.client_api = to_native(&*item, arena)?;
3566        }
3567        Ok(raw)
3568    }
3569}
3570
3571/// An OpenHarmony window to present to, for `MapHandle::attach_ohos_surface()`.
3572///
3573/// Name the window by `window` or by `surface_id`. The session takes its own
3574/// reference to the window, so you can release yours once the call returns.
3575///
3576/// See `mln_ohos_surface_descriptor` in the
3577/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/ohos_8h.html).
3578#[derive(Debug, Clone, Copy, PartialEq)]
3579pub struct OhosSurfaceDescriptor {
3580    pub logical_size: LogicalSize,
3581    /// Your `OHNativeWindow*`, or null to name the window by `surface_id`.
3582    pub window: *mut std::ffi::c_void,
3583    /// The surface ID of a surface in this process, such as the one that
3584    /// `XComponentController.getXComponentSurfaceId()` reports, or 0 to name
3585    /// the window by `window`.
3586    pub surface_id: u64,
3587}
3588impl OhosSurfaceDescriptor {
3589    pub fn new(logical_size: LogicalSize) -> Self {
3590        Self {
3591            logical_size,
3592            window: Default::default(),
3593            surface_id: Default::default(),
3594        }
3595    }
3596}
3597impl ToNative<sys::mln_ohos_surface_descriptor> for OhosSurfaceDescriptor {
3598    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_ohos_surface_descriptor> {
3599        let mut raw: sys::mln_ohos_surface_descriptor = unsafe { std::mem::zeroed() };
3600        raw.size = std::mem::size_of::<sys::mln_ohos_surface_descriptor>() as _;
3601        raw.logical_size = to_native(&self.logical_size, arena)?;
3602        raw.window = self.window;
3603        raw.surface_id = self.surface_id;
3604        Ok(raw)
3605    }
3606}
3607
3608/// A new OpenHarmony window for
3609/// `RenderSessionHandle::set_ohos_surface_target()`.
3610///
3611/// Name the window by `window` or by `surface_id`. The session takes its own
3612/// reference to the window, so you can release yours once the call returns.
3613///
3614/// See `mln_ohos_surface_replacement` in the
3615/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/ohos_8h.html).
3616#[derive(Debug, Clone, Copy, PartialEq)]
3617pub struct OhosSurfaceReplacement {
3618    pub logical_size: LogicalSize,
3619    /// Your `OHNativeWindow*`, or null to name the window by `surface_id`.
3620    pub window: *mut std::ffi::c_void,
3621    /// The surface ID of a surface in this process, such as the one that
3622    /// `XComponentController.getXComponentSurfaceId()` reports, or 0 to name
3623    /// the window by `window`.
3624    pub surface_id: u64,
3625}
3626impl OhosSurfaceReplacement {
3627    pub fn new(logical_size: LogicalSize) -> Self {
3628        Self {
3629            logical_size,
3630            window: Default::default(),
3631            surface_id: Default::default(),
3632        }
3633    }
3634}
3635impl ToNative<sys::mln_ohos_surface_replacement> for OhosSurfaceReplacement {
3636    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_ohos_surface_replacement> {
3637        let mut raw: sys::mln_ohos_surface_replacement = unsafe { std::mem::zeroed() };
3638        raw.size = std::mem::size_of::<sys::mln_ohos_surface_replacement>() as _;
3639        raw.logical_size = to_native(&self.logical_size, arena)?;
3640        raw.window = self.window;
3641        raw.surface_id = self.surface_id;
3642        Ok(raw)
3643    }
3644}
3645
3646/// An OpenGL texture of a borrowed ring.
3647///
3648/// See `mln_open_gl_borrowed_texture` in the
3649/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
3650#[derive(Debug, Clone, Copy, PartialEq)]
3651pub struct OpenGlBorrowedTexture {
3652    /// Your texture name.
3653    pub texture: u32,
3654}
3655impl OpenGlBorrowedTexture {
3656    pub const fn new(texture: u32) -> Self {
3657        Self { texture }
3658    }
3659}
3660impl ToNative<sys::mln_open_gl_borrowed_texture> for OpenGlBorrowedTexture {
3661    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_open_gl_borrowed_texture> {
3662        let mut raw: sys::mln_open_gl_borrowed_texture = unsafe { std::mem::zeroed() };
3663        raw.texture = self.texture;
3664        Ok(raw)
3665    }
3666}
3667
3668/// A ring of your OpenGL textures, for
3669/// `MapHandle::attach_open_gl_borrowed_texture()`.
3670///
3671/// `logical_size` sets the map's size. `physical_width` and `physical_height`
3672/// give the textures' size in pixels, which is usually `logical_size` times the
3673/// map's scale factor. The context must use `OpenGlContextOwnership::Shared`.
3674/// Each texture must be in your context's share group, with storage of that
3675/// size. The ring holds up to `TEXTURE_RING_MAX_DEPTH` distinct textures.
3676///
3677/// The session uses the textures until a replacement or release of the target
3678/// completes, a detach or release of the session completes, or an abandon of it
3679/// returns.
3680///
3681/// See `mln_open_gl_borrowed_texture_descriptor` in the
3682/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
3683#[derive(Debug, Clone, PartialEq)]
3684pub struct OpenGlBorrowedTextureDescriptor<'a> {
3685    pub logical_size: LogicalSize,
3686    pub physical_width: u32,
3687    pub physical_height: u32,
3688    pub context: OpenGlContextDescriptor<'a>,
3689    pub textures: Vec<OpenGlBorrowedTexture>,
3690    /// The textures' target. It must be GL_TEXTURE_2D.
3691    pub target: u32,
3692}
3693impl<'a> OpenGlBorrowedTextureDescriptor<'a> {
3694    pub fn new(
3695        logical_size: LogicalSize,
3696        physical_width: u32,
3697        physical_height: u32,
3698        context: OpenGlContextDescriptor<'a>,
3699        textures: Vec<OpenGlBorrowedTexture>,
3700        target: u32,
3701    ) -> Self {
3702        Self {
3703            logical_size,
3704            physical_width,
3705            physical_height,
3706            context,
3707            textures,
3708            target,
3709        }
3710    }
3711}
3712impl<'a> ToNative<sys::mln_open_gl_borrowed_texture_descriptor>
3713    for OpenGlBorrowedTextureDescriptor<'a>
3714{
3715    fn to_native(
3716        &self,
3717        arena: &mut InputArena,
3718    ) -> Result<sys::mln_open_gl_borrowed_texture_descriptor> {
3719        let mut raw: sys::mln_open_gl_borrowed_texture_descriptor = unsafe { std::mem::zeroed() };
3720        raw.size = std::mem::size_of::<sys::mln_open_gl_borrowed_texture_descriptor>() as _;
3721        raw.logical_size = to_native(&self.logical_size, arena)?;
3722        raw.physical_width = self.physical_width;
3723        raw.physical_height = self.physical_height;
3724        raw.context = to_native(&self.context, arena)?;
3725        raw.textures = convert::array(&self.textures, arena)?;
3726        raw.texture_count = convert::count(self.textures.len())?;
3727        raw.target = self.target;
3728        Ok(raw)
3729    }
3730}
3731
3732/// New OpenGL textures for a borrowed ring, for
3733/// `RenderSessionHandle::set_open_gl_borrowed_texture_target()`.
3734///
3735/// The members and the textures follow the rules of
3736/// `OpenGlBorrowedTextureDescriptor`. The ring keeps its depth, context, and
3737/// texture target, so give it as many textures as it attached with, in the same
3738/// share group.
3739///
3740/// See `mln_open_gl_borrowed_texture_replacement` in the
3741/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
3742#[derive(Debug, Clone, PartialEq)]
3743pub struct OpenGlBorrowedTextureReplacement {
3744    pub logical_size: LogicalSize,
3745    pub physical_width: u32,
3746    pub physical_height: u32,
3747    pub textures: Vec<OpenGlBorrowedTexture>,
3748}
3749impl OpenGlBorrowedTextureReplacement {
3750    pub fn new(
3751        logical_size: LogicalSize,
3752        physical_width: u32,
3753        physical_height: u32,
3754        textures: Vec<OpenGlBorrowedTexture>,
3755    ) -> Self {
3756        Self {
3757            logical_size,
3758            physical_width,
3759            physical_height,
3760            textures,
3761        }
3762    }
3763}
3764impl ToNative<sys::mln_open_gl_borrowed_texture_replacement> for OpenGlBorrowedTextureReplacement {
3765    fn to_native(
3766        &self,
3767        arena: &mut InputArena,
3768    ) -> Result<sys::mln_open_gl_borrowed_texture_replacement> {
3769        let mut raw: sys::mln_open_gl_borrowed_texture_replacement = unsafe { std::mem::zeroed() };
3770        raw.size = std::mem::size_of::<sys::mln_open_gl_borrowed_texture_replacement>() as _;
3771        raw.logical_size = to_native(&self.logical_size, arena)?;
3772        raw.physical_width = self.physical_width;
3773        raw.physical_height = self.physical_height;
3774        raw.textures = convert::array(&self.textures, arena)?;
3775        raw.texture_count = convert::count(self.textures.len())?;
3776        Ok(raw)
3777    }
3778}
3779
3780native_enum! {
3781/// The OpenGL API that a context renders with.
3782///
3783/// See `mln_open_gl_client_api` in the
3784/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
3785pub enum OpenGlClientApi: u32 {
3786    Unspecified = 0,
3787    Gl = 1,
3788    Gles = 2,
3789} Unknown
3790}
3791impl Default for OpenGlClientApi {
3792    fn default() -> Self {
3793        Self::Unspecified
3794    }
3795}
3796
3797/// How a render session gets the OpenGL context that it renders with.
3798///
3799/// Keep the objects that it names alive until a detach or release of the
3800/// session completes, or an abandon of it returns.
3801///
3802/// See `mln_open_gl_context_descriptor` in the
3803/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
3804#[derive(Debug, Clone, PartialEq)]
3805pub struct OpenGlContextDescriptor<'a> {
3806    pub ownership: OpenGlContextOwnership,
3807    pub data: OpenGlContextDescriptorData<'a>,
3808}
3809impl<'a> OpenGlContextDescriptor<'a> {
3810    pub fn new(data: OpenGlContextDescriptorData<'a>) -> Self {
3811        Self {
3812            ownership: Default::default(),
3813            data,
3814        }
3815    }
3816}
3817impl<'a> ToNative<sys::mln_open_gl_context_descriptor> for OpenGlContextDescriptor<'a> {
3818    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_open_gl_context_descriptor> {
3819        let mut raw: sys::mln_open_gl_context_descriptor = unsafe { std::mem::zeroed() };
3820        raw.ownership = to_native(&self.ownership, arena)?;
3821        match &self.data {
3822            OpenGlContextDescriptorData::Wgl(item) => {
3823                raw.platform = sys::MLN_OPEN_GL_CONTEXT_PLATFORM_WGL;
3824                raw.data.wgl = to_native(&(*item), arena)?;
3825            }
3826            OpenGlContextDescriptorData::Egl(item) => {
3827                raw.platform = sys::MLN_OPEN_GL_CONTEXT_PLATFORM_EGL;
3828                raw.data.egl = to_native(&(*item), arena)?;
3829            }
3830            OpenGlContextDescriptorData::WebGl(item) => {
3831                raw.platform = sys::MLN_OPEN_GL_CONTEXT_PLATFORM_WEB_GL;
3832                raw.data.web_gl = to_native(&(*item), arena)?;
3833            }
3834        }
3835        Ok(raw)
3836    }
3837}
3838
3839/// The WGL, EGL, or WebGL part of an OpenGL context descriptor.
3840///
3841/// See `mln_open_gl_context_descriptor_data` in the
3842/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
3843#[derive(Debug, Clone, PartialEq)]
3844pub enum OpenGlContextDescriptorData<'a> {
3845    Wgl(WglContextDescriptor),
3846    Egl(EglContextDescriptor),
3847    WebGl(WebGlContextDescriptor<'a>),
3848}
3849
3850native_enum! {
3851/// Whether a render session's OpenGL context shares objects with yours.
3852///
3853/// See `mln_open_gl_context_ownership` in the
3854/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
3855pub enum OpenGlContextOwnership: u32 {
3856    /// The session's context shares objects with your `share_context`.
3857    Shared = 0,
3858    /// The session's context shares objects with no other context.
3859    Dedicated = 1,
3860} Unknown
3861}
3862impl Default for OpenGlContextOwnership {
3863    fn default() -> Self {
3864        Self::Shared
3865    }
3866}
3867
3868native_flags! {
3869/// An OpenGL context platform, as a bit in a set.
3870///
3871/// See `mln_open_gl_context_provider_flag` in the
3872/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
3873pub struct OpenGlContextProviderFlag: u32 {
3874    const WGL = 1;
3875    const EGL = 2;
3876    const WEB_GL = 4;
3877}
3878}
3879
3880/// An OpenGL surface to present to, for `MapHandle::attach_open_gl_surface()`.
3881///
3882/// The session uses the surface until a replacement or release of the target
3883/// completes, a detach or release of the session completes, or an abandon of it
3884/// returns.
3885///
3886/// See `mln_open_gl_surface_descriptor` in the
3887/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
3888#[derive(Debug, Clone, PartialEq)]
3889pub struct OpenGlSurfaceDescriptor<'a> {
3890    pub logical_size: LogicalSize,
3891    pub context: OpenGlContextDescriptor<'a>,
3892    /// Your EGLSurface with EGL, or your HDC with WGL. WebGL doesn't use it.
3893    pub surface: *mut std::ffi::c_void,
3894}
3895impl<'a> OpenGlSurfaceDescriptor<'a> {
3896    pub fn new(logical_size: LogicalSize, context: OpenGlContextDescriptor<'a>) -> Self {
3897        Self {
3898            logical_size,
3899            context,
3900            surface: Default::default(),
3901        }
3902    }
3903}
3904impl<'a> ToNative<sys::mln_open_gl_surface_descriptor> for OpenGlSurfaceDescriptor<'a> {
3905    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_open_gl_surface_descriptor> {
3906        let mut raw: sys::mln_open_gl_surface_descriptor = unsafe { std::mem::zeroed() };
3907        raw.size = std::mem::size_of::<sys::mln_open_gl_surface_descriptor>() as _;
3908        raw.logical_size = to_native(&self.logical_size, arena)?;
3909        raw.context = to_native(&self.context, arena)?;
3910        raw.surface = self.surface;
3911        Ok(raw)
3912    }
3913}
3914
3915/// A new OpenGL surface for
3916/// `RenderSessionHandle::set_open_gl_surface_target()`.
3917///
3918/// The session presents to it with the context that it attached with. It uses
3919/// the surface until a replacement or release of the target completes, a detach
3920/// or release of the session completes, or an abandon of it returns.
3921///
3922/// See `mln_open_gl_surface_replacement` in the
3923/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
3924#[derive(Debug, Clone, Copy, PartialEq)]
3925pub struct OpenGlSurfaceReplacement {
3926    pub logical_size: LogicalSize,
3927    /// Your EGLSurface with EGL, or your HDC with WGL. WebGL doesn't use it, so
3928    /// leave it null.
3929    pub surface: *mut std::ffi::c_void,
3930}
3931impl OpenGlSurfaceReplacement {
3932    pub fn new(logical_size: LogicalSize) -> Self {
3933        Self {
3934            logical_size,
3935            surface: Default::default(),
3936        }
3937    }
3938}
3939impl ToNative<sys::mln_open_gl_surface_replacement> for OpenGlSurfaceReplacement {
3940    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_open_gl_surface_replacement> {
3941        let mut raw: sys::mln_open_gl_surface_replacement = unsafe { std::mem::zeroed() };
3942        raw.size = std::mem::size_of::<sys::mln_open_gl_surface_replacement>() as _;
3943        raw.logical_size = to_native(&self.logical_size, arena)?;
3944        raw.surface = self.surface;
3945        Ok(raw)
3946    }
3947}
3948
3949/// The OpenGL texture of an acquired frame.
3950///
3951/// See `mln_open_gl_texture_frame` in the
3952/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
3953#[derive(Debug, Clone, Copy, PartialEq, Default)]
3954pub struct OpenGlTextureFrame {
3955    pub width: u32,
3956    pub height: u32,
3957    pub scale_factor: f64,
3958    /// The texture's index in the descriptor's `textures`.
3959    pub slot: u32,
3960    pub texture: u32,
3961    pub target: u32,
3962}
3963impl FromNative<sys::mln_open_gl_texture_frame> for OpenGlTextureFrame {
3964    unsafe fn from_native(raw: sys::mln_open_gl_texture_frame) -> Result<Self> {
3965        Ok(Self {
3966            width: raw.width,
3967            height: raw.height,
3968            scale_factor: raw.scale_factor,
3969            slot: raw.slot,
3970            texture: raw.texture,
3971            target: raw.target,
3972        })
3973    }
3974}
3975
3976/// How a gesture's pan keeps moving the map's content after release.
3977///
3978/// See `mln_pan_momentum` in the
3979/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
3980#[derive(Debug, Clone, Copy, PartialEq, Default)]
3981pub struct PanMomentum {
3982    /// How fast the map's content moved on the screen at release, in logical
3983    /// pixels per second. The pan moves only when this is set.
3984    pub velocity: Option<ScreenPoint>,
3985    pub decay: MomentumDecay,
3986}
3987impl ToNative<sys::mln_pan_momentum> for PanMomentum {
3988    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_pan_momentum> {
3989        let mut raw: sys::mln_pan_momentum = unsafe { std::mem::zeroed() };
3990        raw.fields = 0;
3991        if let Some(item) = &self.velocity {
3992            raw.fields |= sys::MLN_PAN_MOMENTUM_VELOCITY;
3993            raw.velocity = to_native(&*item, arena)?;
3994        }
3995        raw.decay = to_native(&self.decay, arena)?;
3996        Ok(raw)
3997    }
3998}
3999
4000/// An image of 8-bit RGBA pixels whose colors are multiplied by their alpha.
4001///
4002/// See `mln_premultiplied_rgba8_image` in the
4003/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
4004#[derive(Debug, Clone, PartialEq)]
4005pub struct PremultipliedRgba8Image<'a> {
4006    pub width: u32,
4007    pub height: u32,
4008    /// The number of bytes from the start of one row to the start of the next,
4009    /// at least `width` \* 4.
4010    pub stride: u32,
4011    /// The rows of pixels, `stride` bytes apart, from the top row down.
4012    pub pixels: &'a [u8],
4013}
4014impl<'a> PremultipliedRgba8Image<'a> {
4015    pub fn new(width: u32, height: u32, stride: u32, pixels: &'a [u8]) -> Self {
4016        Self {
4017            width,
4018            height,
4019            stride,
4020            pixels,
4021        }
4022    }
4023}
4024impl<'a> ToNative<sys::mln_premultiplied_rgba8_image> for PremultipliedRgba8Image<'a> {
4025    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_premultiplied_rgba8_image> {
4026        let mut raw: sys::mln_premultiplied_rgba8_image = unsafe { std::mem::zeroed() };
4027        raw.size = std::mem::size_of::<sys::mln_premultiplied_rgba8_image>() as _;
4028        raw.width = self.width;
4029        raw.height = self.height;
4030        raw.stride = self.stride;
4031        raw.pixels = self.pixels.as_ptr().cast();
4032        raw.byte_length = convert::count(self.pixels.len())?;
4033        Ok(raw)
4034    }
4035}
4036
4037/// A point in the Web Mercator projection, in meters.
4038///
4039/// See `mln_projected_meters` in the
4040/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
4041#[derive(Debug, Clone, Copy, PartialEq, Default)]
4042pub struct ProjectedMeters {
4043    pub northing: f64,
4044    pub easting: f64,
4045}
4046impl ProjectedMeters {
4047    pub const fn new(northing: f64, easting: f64) -> Self {
4048        Self { northing, easting }
4049    }
4050}
4051impl ToNative<sys::mln_projected_meters> for ProjectedMeters {
4052    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_projected_meters> {
4053        let mut raw: sys::mln_projected_meters = unsafe { std::mem::zeroed() };
4054        raw.northing = self.northing;
4055        raw.easting = self.easting;
4056        Ok(raw)
4057    }
4058}
4059impl FromNative<sys::mln_projected_meters> for ProjectedMeters {
4060    unsafe fn from_native(raw: sys::mln_projected_meters) -> Result<Self> {
4061        Ok(Self {
4062            northing: raw.northing,
4063            easting: raw.easting,
4064        })
4065    }
4066}
4067
4068/// A map's whole projection mode.
4069///
4070/// Its members mean the same as those of `ProjectionModeOptions`.
4071///
4072/// See `mln_projection_mode` in the
4073/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
4074#[derive(Debug, Clone, Copy, PartialEq, Default)]
4075pub struct ProjectionMode {
4076    pub axonometric: bool,
4077    pub x_skew: f64,
4078    pub y_skew: f64,
4079}
4080impl ProjectionMode {
4081    pub const fn new(axonometric: bool, x_skew: f64, y_skew: f64) -> Self {
4082        Self {
4083            axonometric,
4084            x_skew,
4085            y_skew,
4086        }
4087    }
4088}
4089impl ToNative<sys::mln_projection_mode> for ProjectionMode {
4090    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_projection_mode> {
4091        let mut raw: sys::mln_projection_mode = unsafe { std::mem::zeroed() };
4092        raw.axonometric = self.axonometric;
4093        raw.x_skew = self.x_skew;
4094        raw.y_skew = self.y_skew;
4095        Ok(raw)
4096    }
4097}
4098impl FromNative<sys::mln_projection_mode> for ProjectionMode {
4099    unsafe fn from_native(raw: sys::mln_projection_mode) -> Result<Self> {
4100        Ok(Self {
4101            axonometric: raw.axonometric,
4102            x_skew: raw.x_skew,
4103            y_skew: raw.y_skew,
4104        })
4105    }
4106}
4107
4108/// Settings that skew the map or draw it without perspective.
4109///
4110/// See `mln_projection_mode_options` in the
4111/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
4112#[derive(Debug, Clone, Copy, PartialEq, Default)]
4113pub struct ProjectionModeOptions {
4114    /// Whether the map draws without perspective.
4115    pub axonometric: Option<bool>,
4116    pub x_skew: Option<f64>,
4117    pub y_skew: Option<f64>,
4118}
4119impl ToNative<sys::mln_projection_mode_options> for ProjectionModeOptions {
4120    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_projection_mode_options> {
4121        let mut raw: sys::mln_projection_mode_options = unsafe { std::mem::zeroed() };
4122        raw.size = std::mem::size_of::<sys::mln_projection_mode_options>() as _;
4123        raw.fields = 0;
4124        if let Some(item) = &self.axonometric {
4125            raw.fields |= sys::MLN_PROJECTION_MODE_OPTION_AXONOMETRIC;
4126            raw.axonometric = *item;
4127        }
4128        if let Some(item) = &self.x_skew {
4129            raw.fields |= sys::MLN_PROJECTION_MODE_OPTION_X_SKEW;
4130            raw.x_skew = *item;
4131        }
4132        if let Some(item) = &self.y_skew {
4133            raw.fields |= sys::MLN_PROJECTION_MODE_OPTION_Y_SKEW;
4134            raw.y_skew = *item;
4135        }
4136        Ok(raw)
4137    }
4138}
4139
4140/// A rotation, as a quaternion.
4141///
4142/// See `mln_quaternion` in the
4143/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
4144#[derive(Debug, Clone, Copy, PartialEq, Default)]
4145pub struct Quaternion {
4146    pub x: f64,
4147    pub y: f64,
4148    pub z: f64,
4149    pub w: f64,
4150}
4151impl Quaternion {
4152    pub const fn new(x: f64, y: f64, z: f64, w: f64) -> Self {
4153        Self { x, y, z, w }
4154    }
4155}
4156impl ToNative<sys::mln_quaternion> for Quaternion {
4157    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_quaternion> {
4158        let mut raw: sys::mln_quaternion = unsafe { std::mem::zeroed() };
4159        raw.x = self.x;
4160        raw.y = self.y;
4161        raw.z = self.z;
4162        raw.w = self.w;
4163        Ok(raw)
4164    }
4165}
4166impl FromNative<sys::mln_quaternion> for Quaternion {
4167    unsafe fn from_native(raw: sys::mln_quaternion) -> Result<Self> {
4168        Ok(Self {
4169            x: raw.x,
4170            y: raw.y,
4171            z: raw.z,
4172            w: raw.w,
4173        })
4174    }
4175}
4176
4177/// Your lock on a Vulkan queue that you and a render session both submit to.
4178///
4179/// The session holds the lock only while it submits or presents to the queue.
4180/// Set both `lock` and `unlock`, or neither when you don't submit to the queue
4181/// yourself.
4182///
4183/// It can run on a library thread, and it can't call the library.
4184///
4185/// See `mln_queue_lock` in the
4186/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
4187#[derive(Clone, Default)]
4188pub struct QueueLock {
4189    pub lock: Option<std::sync::Arc<dyn Fn() + Send + Sync + 'static>>,
4190    pub unlock: Option<std::sync::Arc<dyn Fn() + Send + Sync + 'static>>,
4191}
4192impl std::fmt::Debug for QueueLock {
4193    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4194        f.debug_struct("QueueLock").finish_non_exhaustive()
4195    }
4196}
4197impl QueueLock {
4198    pub fn with_lock<F>(mut self, callback: F) -> Self
4199    where
4200        F: Fn() + Send + Sync + 'static,
4201    {
4202        self.lock = Some(std::sync::Arc::new(callback));
4203        self
4204    }
4205    pub fn new<F>(callback: F) -> Self
4206    where
4207        F: Fn() + Send + Sync + 'static,
4208    {
4209        Self::default().with_lock(callback)
4210    }
4211    pub fn with_unlock<F>(mut self, callback: F) -> Self
4212    where
4213        F: Fn() + Send + Sync + 'static,
4214    {
4215        self.unlock = Some(std::sync::Arc::new(callback));
4216        self
4217    }
4218    unsafe extern "C" fn lock_trampoline(user_data: *mut std::ffi::c_void) {
4219        // SAFETY: native passes the registration that this trampoline's
4220        // descriptor transferred.
4221        let state = unsafe { callback::state::<Self>(user_data) };
4222        callback::invoke("mln_queue_lock_callback", (), || {
4223            callback::require(&state.lock)?();
4224            Ok(())
4225        })
4226    }
4227    unsafe extern "C" fn unlock_trampoline(user_data: *mut std::ffi::c_void) {
4228        // SAFETY: native passes the registration that this trampoline's
4229        // descriptor transferred.
4230        let state = unsafe { callback::state::<Self>(user_data) };
4231        callback::invoke("mln_queue_lock_callback", (), || {
4232            callback::require(&state.unlock)?();
4233            Ok(())
4234        })
4235    }
4236}
4237impl ToNative<sys::mln_queue_lock> for QueueLock {
4238    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_queue_lock> {
4239        let mut raw: sys::mln_queue_lock = unsafe { std::mem::zeroed() };
4240        raw.lock = self.lock.as_ref().map(|_| Self::lock_trampoline as _);
4241        raw.unlock = self.unlock.as_ref().map(|_| Self::unlock_trampoline as _);
4242        if !(raw.lock.is_none() && raw.unlock.is_none()) {
4243            // SAFETY: the release reclaims exactly this state.
4244            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
4245            raw.release_user_data = Some(callback::release::<Self>);
4246        }
4247        Ok(raw)
4248    }
4249}
4250
4251native_enum! {
4252/// What `RenderSessionHandle::abandon()` did with a session's graphics objects.
4253///
4254/// See `mln_render_abandon_disposition` in the
4255/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4256pub enum RenderAbandonDisposition: u32 {
4257    Clean = 0,
4258    /// It kept some objects that it couldn't destroy safely. They stay
4259    /// allocated until the process exits.
4260    Quarantined = 1,
4261} Unknown
4262}
4263impl Default for RenderAbandonDisposition {
4264    fn default() -> Self {
4265        Self::Clean
4266    }
4267}
4268
4269/// The outcome of `RenderSessionHandle::abandon()`.
4270///
4271/// See `mln_render_abandon_result` in the
4272/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4273#[derive(Debug, Clone, Copy, PartialEq, Default)]
4274pub struct RenderAbandonResult {
4275    pub disposition: RenderAbandonDisposition,
4276    pub quarantined_resource_count: u32,
4277}
4278impl FromNative<sys::mln_render_abandon_result> for RenderAbandonResult {
4279    unsafe fn from_native(raw: sys::mln_render_abandon_result) -> Result<Self> {
4280        Ok(Self {
4281            disposition: RenderAbandonDisposition::from_raw(raw.disposition),
4282            quarantined_resource_count: raw.quarantined_resource_count,
4283        })
4284    }
4285}
4286
4287native_flags! {
4288/// A render backend, as a bit in a set.
4289///
4290/// See `mln_render_backend_flag` in the
4291/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/base_8h.html).
4292pub struct RenderBackendFlag: u32 {
4293    const METAL = 1;
4294    const VULKAN = 2;
4295    const OPEN_GL = 4;
4296    const WEB_GPU = 8;
4297}
4298}
4299
4300native_enum! {
4301/// The thread that runs a render session's graphics work.
4302///
4303/// See `mln_render_driver_kind` in the
4304/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
4305pub enum RenderDriverKind: u32 {
4306    /// A library thread.
4307    CoreWorker = 1,
4308    /// Your thread, when it calls `RenderSessionHandle::service_driver_work()`.
4309    CallerGraphicsThread = 2,
4310} Unknown
4311}
4312
4313/// How one frame demand finished.
4314///
4315/// See `mln_render_frame_result` in the
4316/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4317#[derive(Debug, Clone, Copy, PartialEq, Default)]
4318pub struct RenderFrameResult {
4319    pub disposition: RenderResult,
4320    pub token: u64,
4321    /// The map update that a rendered frame shows. The frame includes a
4322    /// command's change when this is at least the command's
4323    /// `CommandCompletion::render_update_generation`.
4324    pub map_update_generation: u64,
4325    pub generation: u64,
4326    pub frame_generation: u64,
4327    pub needs_repaint: bool,
4328    /// The camera and extent that a rendered frame shows.
4329    pub view: MapView,
4330    pub mode: RenderMode,
4331}
4332impl FromNative<sys::mln_render_frame_result> for RenderFrameResult {
4333    unsafe fn from_native(raw: sys::mln_render_frame_result) -> Result<Self> {
4334        Ok(Self {
4335            disposition: RenderResult::from_raw(raw.disposition),
4336            token: raw.token,
4337            map_update_generation: raw.map_update_generation,
4338            generation: raw.generation,
4339            frame_generation: raw.frame_generation,
4340            needs_repaint: raw.needs_repaint,
4341            view: unsafe { from_native(raw.view) }?,
4342            mode: RenderMode::from_raw(raw.mode),
4343        })
4344    }
4345}
4346
4347native_enum! {
4348/// Whether a frame drew the map complete, or lacked resources that are still
4349/// loading.
4350///
4351/// See `mln_render_mode` in the
4352/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4353pub enum RenderMode: u32 {
4354    Partial = 0,
4355    Full = 1,
4356} Unknown
4357}
4358impl Default for RenderMode {
4359    fn default() -> Self {
4360        Self::Partial
4361    }
4362}
4363
4364native_enum! {
4365/// How a frame demand finished.
4366///
4367/// See `mln_render_result` in the
4368/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4369pub enum RenderResult: u32 {
4370    Rendered = 0,
4371    /// The map had nothing new to draw.
4372    NoUpdate = 1,
4373    /// The target couldn't take a frame, such as while a window is hidden or
4374    /// destroyed, or after `RenderSessionHandle::release_target()`. Demand a
4375    /// frame again later.
4376    TargetNotReady = 2,
4377    /// A later demand with the same flags replaced this one.
4378    Superseded = 3,
4379    /// The session failed, and `RenderSessionHandle::get_failure()` reports
4380    /// why. Once `RenderSessionHandle::release()` completes, you can attach a
4381    /// new session.
4382    Failed = 4,
4383} Unknown
4384}
4385impl Default for RenderResult {
4386    fn default() -> Self {
4387        Self::Rendered
4388    }
4389}
4390
4391/// Options for attaching a render session to a map.
4392///
4393/// See `mln_render_session_attach_options` in the
4394/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
4395#[derive(Debug, Clone)]
4396pub struct RenderSessionAttachOptions {
4397    /// The thread that runs the session's graphics work, which depends on the
4398    /// target:
4399    ///
4400    /// - `RenderDriverKind::CallerGraphicsThread` for a shared or dedicated EGL
4401    ///   or WGL context, an existing WebGL context, or a browser's WebGPU
4402    ///   device.
4403    /// - `RenderDriverKind::CoreWorker` for a transferred WebGL canvas, an
4404    ///   Android, OpenHarmony, or Win32 window, a Wayland surface, a ring of
4405    ///   Android hardware buffers, dmabufs, DXGI shared textures, or
4406    ///   IOSurfaces, or an offscreen session.
4407    /// - Either one for another Metal or Vulkan target.
4408    ///
4409    /// An attach with another driver fails with `Status::Unsupported`.
4410    pub driver: RenderDriverKind,
4411    /// The kinds of `GpuSync` that you can wait on before you read an acquired
4412    /// frame. The session uses one of them that its target supports. Zero lets
4413    /// the session pick a kind that names no object to wait on.
4414    pub producer_sync_kinds: GpuSyncKindFlag,
4415    /// Called when frame results are waiting for
4416    /// `RenderSessionHandle::drain_frame_results()`. It isn't called again
4417    /// until a drain takes them.
4418    pub frame_wake: Wake,
4419    /// Called when the session has something new to draw. Demand a frame at
4420    /// your next display refresh. It isn't called again until you demand a
4421    /// frame, or while the session has no target.
4422    pub redraw_wake: Wake,
4423    /// Called when a session driven by `RenderDriverKind::CallerGraphicsThread`
4424    /// has work for `RenderSessionHandle::service_driver_work()`. It isn't
4425    /// called again until a service runs.
4426    pub driver_work_wake: Wake,
4427    /// Your lock on the Vulkan queue, when you submit to it yourself.
4428    pub queue_lock: QueueLock,
4429}
4430impl RenderSessionAttachOptions {
4431    pub fn new(driver: RenderDriverKind) -> Self {
4432        Self {
4433            driver,
4434            producer_sync_kinds: Default::default(),
4435            frame_wake: Default::default(),
4436            redraw_wake: Default::default(),
4437            driver_work_wake: Default::default(),
4438            queue_lock: Default::default(),
4439        }
4440    }
4441}
4442impl ToNative<sys::mln_render_session_attach_options> for RenderSessionAttachOptions {
4443    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_render_session_attach_options> {
4444        let mut raw: sys::mln_render_session_attach_options = unsafe { std::mem::zeroed() };
4445        raw.size = std::mem::size_of::<sys::mln_render_session_attach_options>() as _;
4446        raw.driver = to_native(&self.driver, arena)?;
4447        raw.producer_sync_kinds = to_native(&self.producer_sync_kinds, arena)?;
4448        raw.frame_wake = to_native(&self.frame_wake, arena)?;
4449        raw.redraw_wake = to_native(&self.redraw_wake, arena)?;
4450        raw.driver_work_wake = to_native(&self.driver_work_wake, arena)?;
4451        raw.queue_lock = to_native(&self.queue_lock, arena)?;
4452        Ok(raw)
4453    }
4454}
4455
4456/// What an attached render session supports.
4457///
4458/// See `mln_render_session_capabilities` in the
4459/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
4460#[derive(Debug, Clone, Copy, PartialEq)]
4461pub struct RenderSessionCapabilities {
4462    pub driver: RenderDriverKind,
4463    /// How many textures the session's texture ring has.
4464    pub texture_ring_depth: u32,
4465    pub flags: RenderSessionCapabilityFlag,
4466    /// The kind of `GpuSync` that `AcquiredFrameView::get_producer_sync()`
4467    /// reports.
4468    pub producer_sync_kind: GpuSyncKind,
4469    /// The kinds of `GpuSync` that `AcquiredFrameHandle::release()` accepts.
4470    /// They depend on the target and on what the device supports.
4471    pub consumer_sync_kinds: GpuSyncKindFlag,
4472}
4473impl FromNative<sys::mln_render_session_capabilities> for RenderSessionCapabilities {
4474    unsafe fn from_native(raw: sys::mln_render_session_capabilities) -> Result<Self> {
4475        Ok(Self {
4476            driver: RenderDriverKind::from_raw(raw.driver),
4477            texture_ring_depth: raw.texture_ring_depth,
4478            flags: RenderSessionCapabilityFlag::from_bits_retain(raw.flags),
4479            producer_sync_kind: GpuSyncKind::from_raw(raw.producer_sync_kind),
4480            consumer_sync_kinds: GpuSyncKindFlag::from_bits_retain(raw.consumer_sync_kinds),
4481        })
4482    }
4483}
4484
4485native_flags! {
4486/// Something that a render session can do.
4487///
4488/// See `mln_render_session_capability_flag` in the
4489/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
4490pub struct RenderSessionCapabilityFlag: u32 {
4491    /// `RenderSessionHandle::acquire_frame()` can take the frames it renders.
4492    const FRAME_ACQUISITION = 1;
4493    /// `RenderSessionHandle::read_texture()` can copy its texture to memory.
4494    const READBACK = 2;
4495    /// It shows frames on a surface.
4496    const PRESENTATION = 4;
4497}
4498}
4499
4500/// The state of a render session at one moment.
4501///
4502/// See `mln_render_session_snapshot` in the
4503/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4504#[derive(Debug, Clone, Copy, PartialEq)]
4505pub struct RenderSessionSnapshot {
4506    pub state: RenderSessionState,
4507    /// The target's logical size, and the map's scale factor.
4508    pub extent: LogicalExtent,
4509    pub generation: u64,
4510    pub frame_generation: u64,
4511    pub acquired_frame_count: u32,
4512    /// `Status::Ok` until the session fails. Then `Status::TargetLost` when it
4513    /// failed because it lost its target, or `Status::NativeError` when it
4514    /// failed for another reason.
4515    pub failure_status: Status,
4516    /// Whether the session is attached and has a target to render to. It's
4517    /// false from when `RenderSessionHandle::release_target()` completes until
4518    /// you give the session a new target.
4519    pub has_target: bool,
4520}
4521impl FromNative<sys::mln_render_session_snapshot> for RenderSessionSnapshot {
4522    unsafe fn from_native(raw: sys::mln_render_session_snapshot) -> Result<Self> {
4523        Ok(Self {
4524            state: RenderSessionState::from_raw(raw.state),
4525            extent: unsafe { from_native(raw.extent) }?,
4526            generation: raw.generation,
4527            frame_generation: raw.frame_generation,
4528            acquired_frame_count: raw.acquired_frame_count,
4529            failure_status: Status::from_raw(raw.failure_status),
4530            has_target: raw.has_target,
4531        })
4532    }
4533}
4534
4535native_enum! {
4536/// Where a render session is in its life.
4537///
4538/// See `mln_render_session_state` in the
4539/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
4540pub enum RenderSessionState: u32 {
4541    Attaching = 1,
4542    Attached = 2,
4543    Detaching = 3,
4544    Detached = 4,
4545    Failed = 5,
4546    Abandoned = 6,
4547} Unknown
4548}
4549
4550/// A feature that a rendered feature query found.
4551///
4552/// See `mln_rendered_feature` in the
4553/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
4554#[derive(Debug, Clone, PartialEq, Default)]
4555pub struct RenderedFeature {
4556    /// The feature, as a GeoJSON feature.
4557    pub feature: String,
4558    /// The layer that drew the feature.
4559    pub layer_id: String,
4560    pub source_id: String,
4561    /// The feature's source layer, or empty when its source has none.
4562    pub source_layer_id: String,
4563    /// The feature's state, as a JSON object.
4564    pub state: String,
4565}
4566impl FromNative<sys::mln_rendered_feature> for RenderedFeature {
4567    unsafe fn from_native(raw: sys::mln_rendered_feature) -> Result<Self> {
4568        Ok(Self {
4569            feature: unsafe { from_native(raw.feature) }?,
4570            layer_id: unsafe { from_native(raw.layer_id) }?,
4571            source_id: unsafe { from_native(raw.source_id) }?,
4572            source_layer_id: unsafe { from_native(raw.source_layer_id) }?,
4573            state: unsafe { from_native(raw.state) }?,
4574        })
4575    }
4576}
4577
4578/// Options for a rendered feature query.
4579///
4580/// See `mln_rendered_feature_query_options` in the
4581/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
4582#[derive(Debug, Clone, PartialEq, Default)]
4583pub struct RenderedFeatureQueryOptions<'a> {
4584    /// The layers to query. Without them, the query covers every layer.
4585    pub layer_ids: Option<&'a [&'a str]>,
4586    /// A \[filter\](https://maplibre.org/maplibre-style-spec/expressions/) that
4587    /// each feature must match. Empty matches every feature.
4588    pub filter: &'a str,
4589}
4590impl<'a> ToNative<sys::mln_rendered_feature_query_options> for RenderedFeatureQueryOptions<'a> {
4591    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_rendered_feature_query_options> {
4592        let mut raw: sys::mln_rendered_feature_query_options = unsafe { std::mem::zeroed() };
4593        raw.size = std::mem::size_of::<sys::mln_rendered_feature_query_options>() as _;
4594        raw.fields = 0;
4595        if let Some(item) = &self.layer_ids {
4596            raw.fields |= sys::MLN_RENDERED_FEATURE_QUERY_OPTION_LAYER_IDS;
4597            raw.layer_ids = convert::array(&*item, arena)?;
4598        }
4599        raw.layer_id_count =
4600            convert::count(self.layer_ids.as_ref().map_or(0, |items| items.len()))?;
4601        raw.filter = to_native(&self.filter, arena)?;
4602        Ok(raw)
4603    }
4604}
4605
4606/// The screen area that a rendered feature query covers.
4607///
4608/// See `mln_rendered_query_geometry` in the
4609/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
4610#[derive(Debug, Clone, PartialEq)]
4611pub enum RenderedQueryGeometry {
4612    Point(ScreenPoint),
4613    Box(ScreenBox),
4614    LineString(ScreenLineString),
4615}
4616impl ToNative<sys::mln_rendered_query_geometry> for RenderedQueryGeometry {
4617    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_rendered_query_geometry> {
4618        let mut raw: sys::mln_rendered_query_geometry = unsafe { std::mem::zeroed() };
4619        raw.size = std::mem::size_of::<sys::mln_rendered_query_geometry>() as _;
4620        match self {
4621            RenderedQueryGeometry::Point(item) => {
4622                raw.type_ = sys::MLN_RENDERED_QUERY_GEOMETRY_TYPE_POINT;
4623                raw.data.point = to_native(&(*item), arena)?;
4624            }
4625            RenderedQueryGeometry::Box(item) => {
4626                raw.type_ = sys::MLN_RENDERED_QUERY_GEOMETRY_TYPE_BOX;
4627                raw.data.box_ = to_native(&(*item), arena)?;
4628            }
4629            RenderedQueryGeometry::LineString(item) => {
4630                raw.type_ = sys::MLN_RENDERED_QUERY_GEOMETRY_TYPE_LINE_STRING;
4631                raw.data.line_string = to_native(&(*item), arena)?;
4632            }
4633        }
4634        Ok(raw)
4635    }
4636}
4637
4638/// Statistics about the frames that a map renders.
4639///
4640/// See `mln_rendering_stats` in the
4641/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4642#[derive(Debug, Clone, Copy, PartialEq, Default)]
4643pub struct RenderingStats {
4644    /// The time that the frame took to encode, in milliseconds.
4645    pub encoding_time_ms: f64,
4646    /// The time that the frame took to render, in milliseconds.
4647    pub rendering_time_ms: f64,
4648    /// The frames rendered so far.
4649    pub frame_count: i64,
4650    /// The draw calls in the frame.
4651    pub draw_call_count: i64,
4652    /// The draw calls in every frame so far.
4653    pub total_draw_call_count: i64,
4654}
4655impl FromNative<sys::mln_rendering_stats> for RenderingStats {
4656    unsafe fn from_native(raw: sys::mln_rendering_stats) -> Result<Self> {
4657        Ok(Self {
4658            encoding_time_ms: raw.encoding_time_ms,
4659            rendering_time_ms: raw.rendering_time_ms,
4660            frame_count: raw.frame_count,
4661            draw_call_count: raw.draw_call_count,
4662            total_draw_call_count: raw.total_draw_call_count,
4663        })
4664    }
4665}
4666
4667native_enum! {
4668/// Why a resource request failed.
4669///
4670/// See `mln_resource_error_reason` in the
4671/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4672pub enum ResourceErrorReason: u32 {
4673    /// A reason that no other value names.
4674    Other = 0,
4675    NotFound = 1,
4676    /// The server reported an error.
4677    Server = 2,
4678    /// The server couldn't be reached.
4679    Connection = 3,
4680    RateLimit = 4,
4681} Unknown
4682}
4683impl Default for ResourceErrorReason {
4684    fn default() -> Self {
4685        Self::Other
4686    }
4687}
4688
4689native_enum! {
4690/// The kind of a resource that the library loads.
4691///
4692/// See `mln_resource_kind` in the
4693/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4694pub enum ResourceKind: u32 {
4695    Unknown = 0,
4696    Style = 1,
4697    Source = 2,
4698    Tile = 3,
4699    Glyphs = 4,
4700    SpriteImage = 5,
4701    SpriteJson = 6,
4702    Image = 7,
4703} Unrecognized
4704}
4705impl Default for ResourceKind {
4706    fn default() -> Self {
4707        Self::Unknown
4708    }
4709}
4710
4711native_flags! {
4712/// A resource kind, as a bit in a set.
4713///
4714/// See `mln_resource_kind_flag` in the
4715/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4716pub struct ResourceKindFlag: u32 {
4717    const UNKNOWN = 1;
4718    const STYLE = 2;
4719    const SOURCE = 4;
4720    const TILE = 8;
4721    const GLYPHS = 16;
4722    const SPRITE_IMAGE = 32;
4723    const SPRITE_JSON = 64;
4724    const IMAGE = 128;
4725    const ALL = 255;
4726}
4727}
4728
4729native_enum! {
4730/// Where a request may load its resource from.
4731///
4732/// See `mln_resource_loading_method` in the
4733/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4734pub enum ResourceLoadingMethod: u32 {
4735    /// The cache or the network.
4736    All = 0,
4737    CacheOnly = 1,
4738    NetworkOnly = 2,
4739} Unknown
4740}
4741impl Default for ResourceLoadingMethod {
4742    fn default() -> Self {
4743        Self::All
4744    }
4745}
4746
4747native_enum! {
4748/// The priority of a resource request.
4749///
4750/// See `mln_resource_priority` in the
4751/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4752pub enum ResourcePriority: u32 {
4753    Regular = 0,
4754    Low = 1,
4755} Unknown
4756}
4757impl Default for ResourcePriority {
4758    fn default() -> Self {
4759        Self::Regular
4760    }
4761}
4762
4763/// A resource provider, for `RuntimeHandle::set_resource_provider()`.
4764///
4765/// See `mln_resource_provider` in the
4766/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4767#[derive(Clone)]
4768pub struct ResourceProvider {
4769    /// The callback receives (`request`, `handle`).
4770    pub callback:
4771        std::sync::Arc<dyn Fn(ResourceRequestInfo, ResourceRequestHandle) + Send + Sync + 'static>,
4772    /// The requests that the provider serves. Without routes, it serves every
4773    /// network request.
4774    pub routes: Vec<ResourceRoute>,
4775}
4776impl std::fmt::Debug for ResourceProvider {
4777    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4778        f.debug_struct("ResourceProvider").finish_non_exhaustive()
4779    }
4780}
4781impl ResourceProvider {
4782    pub fn new<F>(callback: F) -> Self
4783    where
4784        F: Fn(ResourceRequestInfo, ResourceRequestHandle) + Send + Sync + 'static,
4785    {
4786        Self {
4787            callback: std::sync::Arc::new(callback),
4788            routes: Default::default(),
4789        }
4790    }
4791    unsafe extern "C" fn callback_trampoline(
4792        user_data: *mut std::ffi::c_void,
4793        request: *const sys::mln_resource_request_info,
4794        handle: sys::mln_resource_request,
4795    ) {
4796        // SAFETY: native passes the registration that this trampoline's
4797        // descriptor transferred.
4798        let state = unsafe { callback::state::<Self>(user_data) };
4799        callback::invoke("mln_resource_provider_callback", (), || {
4800            let handle = ResourceRequestHandle::adopt(handle)?;
4801            (state.callback)(unsafe { convert::copy_reference(request) }?, handle);
4802            Ok(())
4803        })
4804    }
4805}
4806impl ToNative<sys::mln_resource_provider> for ResourceProvider {
4807    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_provider> {
4808        let mut raw: sys::mln_resource_provider = unsafe { std::mem::zeroed() };
4809        raw.size = std::mem::size_of::<sys::mln_resource_provider>() as _;
4810        raw.callback = Some(Self::callback_trampoline as _);
4811        raw.routes = convert::array(&self.routes, arena)?;
4812        raw.route_count = convert::count(self.routes.len())?;
4813        if !(raw.callback.is_none()) {
4814            // SAFETY: the release reclaims exactly this state.
4815            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
4816            raw.release_user_data = Some(callback::release::<Self>);
4817        }
4818        Ok(raw)
4819    }
4820}
4821
4822/// The bytes from `start` to `end` of a resource, both included.
4823///
4824/// See `mln_resource_range` in the
4825/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4826#[derive(Debug, Clone, Copy, PartialEq, Default)]
4827pub struct ResourceRange {
4828    pub start: u64,
4829    pub end: u64,
4830}
4831impl FromNative<sys::mln_resource_range> for ResourceRange {
4832    unsafe fn from_native(raw: sys::mln_resource_range) -> Result<Self> {
4833        Ok(Self {
4834            start: raw.start,
4835            end: raw.end,
4836        })
4837    }
4838}
4839
4840/// A cancel callback, for `ResourceRequestHandle::set_cancel_callback()`.
4841///
4842/// See `mln_resource_request_cancel_handler` in the
4843/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4844#[derive(Clone)]
4845pub struct ResourceRequestCancelHandler {
4846    pub callback: std::sync::Arc<dyn Fn() + Send + Sync + 'static>,
4847}
4848impl std::fmt::Debug for ResourceRequestCancelHandler {
4849    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4850        f.debug_struct("ResourceRequestCancelHandler")
4851            .finish_non_exhaustive()
4852    }
4853}
4854impl ResourceRequestCancelHandler {
4855    pub fn new<F>(callback: F) -> Self
4856    where
4857        F: Fn() + Send + Sync + 'static,
4858    {
4859        Self {
4860            callback: std::sync::Arc::new(callback),
4861        }
4862    }
4863    unsafe extern "C" fn callback_trampoline(
4864        user_data: *mut std::ffi::c_void,
4865        _handle: sys::mln_resource_request,
4866    ) {
4867        // SAFETY: native passes the registration that this trampoline's
4868        // descriptor transferred.
4869        let state = unsafe { callback::state::<Self>(user_data) };
4870        callback::invoke("mln_resource_request_cancel_callback", (), || {
4871            (state.callback)();
4872            Ok(())
4873        })
4874    }
4875}
4876impl ToNative<sys::mln_resource_request_cancel_handler> for ResourceRequestCancelHandler {
4877    fn to_native(
4878        &self,
4879        arena: &mut InputArena,
4880    ) -> Result<sys::mln_resource_request_cancel_handler> {
4881        let mut raw: sys::mln_resource_request_cancel_handler = unsafe { std::mem::zeroed() };
4882        raw.size = std::mem::size_of::<sys::mln_resource_request_cancel_handler>() as _;
4883        raw.callback = Some(Self::callback_trampoline as _);
4884        if !(raw.callback.is_none()) {
4885            // SAFETY: the release reclaims exactly this state.
4886            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
4887            raw.release_user_data = Some(callback::release::<Self>);
4888        }
4889        Ok(raw)
4890    }
4891}
4892
4893/// A request that a resource provider serves.
4894///
4895/// When the cache holds an earlier copy of the resource, the `prior_` fields
4896/// describe it.
4897///
4898/// See `mln_resource_request_info` in the
4899/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4900#[derive(Debug, Clone, PartialEq, Default)]
4901pub struct ResourceRequestInfo {
4902    /// The URL as the style names it.
4903    pub requested_url: String,
4904    /// The URL to load, after the library expands any shorthand in
4905    /// `requested_url` and before any resource transform. Routes match this
4906    /// URL.
4907    pub resolved_url: String,
4908    pub kind: ResourceKind,
4909    pub loading_method: ResourceLoadingMethod,
4910    pub priority: ResourcePriority,
4911    pub usage: ResourceUsage,
4912    pub storage_policy: ResourceStoragePolicy,
4913    /// The only bytes of the resource that the request wants.
4914    pub range: Option<ResourceRange>,
4915    pub prior_modified_unix_ms: Option<i64>,
4916    pub prior_expires_unix_ms: Option<i64>,
4917    /// Empty when the earlier copy has no ETag.
4918    pub prior_etag: String,
4919    pub prior_data: Vec<u8>,
4920}
4921impl FromNative<sys::mln_resource_request_info> for ResourceRequestInfo {
4922    unsafe fn from_native(raw: sys::mln_resource_request_info) -> Result<Self> {
4923        Ok(Self {
4924            requested_url: unsafe { from_native(raw.requested_url) }?,
4925            resolved_url: unsafe { from_native(raw.resolved_url) }?,
4926            kind: ResourceKind::from_raw(raw.kind),
4927            loading_method: ResourceLoadingMethod::from_raw(raw.loading_method),
4928            priority: ResourcePriority::from_raw(raw.priority),
4929            usage: ResourceUsage::from_raw(raw.usage),
4930            storage_policy: ResourceStoragePolicy::from_raw(raw.storage_policy),
4931            range: unsafe {
4932                convert::present(raw.fields, sys::MLN_RESOURCE_REQUEST_RANGE, raw.range)
4933            }?,
4934            prior_modified_unix_ms: (raw.fields & sys::MLN_RESOURCE_REQUEST_PRIOR_MODIFIED != 0)
4935                .then_some(raw.prior_modified_unix_ms),
4936            prior_expires_unix_ms: (raw.fields & sys::MLN_RESOURCE_REQUEST_PRIOR_EXPIRES != 0)
4937                .then_some(raw.prior_expires_unix_ms),
4938            prior_etag: unsafe { from_native(raw.prior_etag) }?,
4939            prior_data: unsafe { convert::counted(raw.prior_data, raw.prior_data_size) }?,
4940        })
4941    }
4942}
4943
4944/// The answer to a resource request.
4945///
4946/// See `mln_resource_response` in the
4947/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
4948#[derive(Debug, Clone, PartialEq, Default)]
4949pub struct ResourceResponse<'a> {
4950    pub status: ResourceResponseStatus,
4951    /// Why the request failed, for `ResourceResponseStatus::Error`.
4952    pub error_reason: ResourceErrorReason,
4953    /// The resource, for `ResourceResponseStatus::Ok`.
4954    pub bytes: &'a [u8],
4955    /// A description of the error, for `ResourceResponseStatus::Error`.
4956    pub error_message: &'a str,
4957    /// Whether the library must request the resource again before it reuses
4958    /// this copy.
4959    pub must_revalidate: bool,
4960    pub modified_unix_ms: Option<i64>,
4961    pub expires_unix_ms: Option<i64>,
4962    /// Empty when the resource has no ETag.
4963    pub etag: &'a str,
4964    /// When to retry, for `ResourceResponseStatus::Error`.
4965    pub retry_after_unix_ms: Option<i64>,
4966}
4967impl<'a> ToNative<sys::mln_resource_response> for ResourceResponse<'a> {
4968    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_response> {
4969        let mut raw: sys::mln_resource_response = unsafe { std::mem::zeroed() };
4970        raw.size = std::mem::size_of::<sys::mln_resource_response>() as _;
4971        raw.fields = 0;
4972        raw.status = to_native(&self.status, arena)?;
4973        raw.error_reason = to_native(&self.error_reason, arena)?;
4974        raw.bytes = self.bytes.as_ptr().cast();
4975        raw.byte_count = convert::count(self.bytes.len())?;
4976        raw.error_message = to_native(&self.error_message, arena)?;
4977        raw.must_revalidate = self.must_revalidate;
4978        if let Some(item) = &self.modified_unix_ms {
4979            raw.fields |= sys::MLN_RESOURCE_RESPONSE_MODIFIED;
4980            raw.modified_unix_ms = *item;
4981        }
4982        if let Some(item) = &self.expires_unix_ms {
4983            raw.fields |= sys::MLN_RESOURCE_RESPONSE_EXPIRES;
4984            raw.expires_unix_ms = *item;
4985        }
4986        raw.etag = to_native(&self.etag, arena)?;
4987        if let Some(item) = &self.retry_after_unix_ms {
4988            raw.fields |= sys::MLN_RESOURCE_RESPONSE_RETRY_AFTER;
4989            raw.retry_after_unix_ms = *item;
4990        }
4991        Ok(raw)
4992    }
4993}
4994
4995native_enum! {
4996/// The outcome of a resource request.
4997///
4998/// See `mln_resource_response_status` in the
4999/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5000pub enum ResourceResponseStatus: u32 {
5001    Ok = 0,
5002    Error = 1,
5003    /// The resource exists and is empty.
5004    NoContent = 2,
5005    /// The earlier copy that the request's `prior_` fields describe is current.
5006    NotModified = 3,
5007} Unknown
5008}
5009impl Default for ResourceResponseStatus {
5010    fn default() -> Self {
5011        Self::Ok
5012    }
5013}
5014
5015/// The requests that a resource provider serves.
5016///
5017/// See `mln_resource_route` in the
5018/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5019#[derive(Debug, Clone, PartialEq, Default)]
5020pub struct ResourceRoute {
5021    /// The kinds of resource that the route covers. Zero covers every kind.
5022    pub kinds: ResourceKindFlag,
5023    pub flags: UrlMatchFlag,
5024    pub url: String,
5025}
5026impl ToNative<sys::mln_resource_route> for ResourceRoute {
5027    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_route> {
5028        let mut raw: sys::mln_resource_route = unsafe { std::mem::zeroed() };
5029        raw.size = std::mem::size_of::<sys::mln_resource_route>() as _;
5030        raw.kinds = to_native(&self.kinds, arena)?;
5031        raw.flags = to_native(&self.flags, arena)?;
5032        raw.url = to_native(&self.url, arena)?;
5033        Ok(raw)
5034    }
5035}
5036
5037native_enum! {
5038/// Whether the library keeps a loaded resource in its cache.
5039///
5040/// See `mln_resource_storage_policy` in the
5041/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5042pub enum ResourceStoragePolicy: u32 {
5043    Permanent = 0,
5044    Volatile = 1,
5045} Unknown
5046}
5047impl Default for ResourceStoragePolicy {
5048    fn default() -> Self {
5049        Self::Permanent
5050    }
5051}
5052
5053/// How to rewrite request URLs, for `RuntimeHandle::set_resource_transform()`.
5054///
5055/// Set either `callback` or `rules`, not both.
5056///
5057/// See `mln_resource_transform` in the
5058/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5059#[derive(Clone, Default)]
5060pub struct ResourceTransform {
5061    /// The callback receives (`kind`, `url`, `request`).
5062    pub callback: Option<
5063        std::sync::Arc<
5064            dyn Fn(ResourceKind, &str, ResourceTransformRequestHandle) + Send + Sync + 'static,
5065        >,
5066    >,
5067    /// The first rule that matches a request adds its parameters, and no other.
5068    /// A request that no rule matches keeps its URL.
5069    pub rules: Vec<ResourceTransformRule>,
5070}
5071impl std::fmt::Debug for ResourceTransform {
5072    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5073        f.debug_struct("ResourceTransform").finish_non_exhaustive()
5074    }
5075}
5076impl ResourceTransform {
5077    pub fn with_callback<F>(mut self, callback: F) -> Self
5078    where
5079        F: Fn(ResourceKind, &str, ResourceTransformRequestHandle) + Send + Sync + 'static,
5080    {
5081        self.callback = Some(std::sync::Arc::new(callback));
5082        self
5083    }
5084    pub fn new<F>(callback: F) -> Self
5085    where
5086        F: Fn(ResourceKind, &str, ResourceTransformRequestHandle) + Send + Sync + 'static,
5087    {
5088        Self::default().with_callback(callback)
5089    }
5090    unsafe extern "C" fn callback_trampoline(
5091        user_data: *mut std::ffi::c_void,
5092        kind: sys::mln_resource_kind,
5093        url: sys::mln_buffer_view,
5094        request: sys::mln_resource_transform_request,
5095    ) {
5096        // SAFETY: native passes the registration that this trampoline's
5097        // descriptor transferred.
5098        let state = unsafe { callback::state::<Self>(user_data) };
5099        callback::invoke("mln_resource_transform_callback", (), || {
5100            let request = ResourceTransformRequestHandle::adopt(request)?;
5101            callback::require(&state.callback)?(
5102                ResourceKind::from_raw(kind),
5103                unsafe { crate::string::borrow_string_view(url) }?,
5104                request,
5105            );
5106            Ok(())
5107        })
5108    }
5109}
5110impl ToNative<sys::mln_resource_transform> for ResourceTransform {
5111    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_transform> {
5112        let mut raw: sys::mln_resource_transform = unsafe { std::mem::zeroed() };
5113        raw.size = std::mem::size_of::<sys::mln_resource_transform>() as _;
5114        raw.callback = self
5115            .callback
5116            .as_ref()
5117            .map(|_| Self::callback_trampoline as _);
5118        raw.rules = convert::array(&self.rules, arena)?;
5119        raw.rule_count = convert::count(self.rules.len())?;
5120        if !(raw.callback.is_none()) {
5121            // SAFETY: the release reclaims exactly this state.
5122            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
5123            raw.release_user_data = Some(callback::release::<Self>);
5124        }
5125        Ok(raw)
5126    }
5127}
5128
5129/// Why a resource transform fails a request.
5130///
5131/// See `mln_resource_transform_error` in the
5132/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5133#[derive(Debug, Clone, PartialEq, Default)]
5134pub struct ResourceTransformError<'a> {
5135    pub reason: ResourceErrorReason,
5136    pub message: &'a str,
5137    /// When to retry, for `ResourceErrorReason::RateLimit`.
5138    pub retry_after_unix_ms: Option<i64>,
5139}
5140impl<'a> ToNative<sys::mln_resource_transform_error> for ResourceTransformError<'a> {
5141    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_transform_error> {
5142        let mut raw: sys::mln_resource_transform_error = unsafe { std::mem::zeroed() };
5143        raw.size = std::mem::size_of::<sys::mln_resource_transform_error>() as _;
5144        raw.fields = 0;
5145        raw.reason = to_native(&self.reason, arena)?;
5146        raw.message = to_native(&self.message, arena)?;
5147        if let Some(item) = &self.retry_after_unix_ms {
5148            raw.fields |= sys::MLN_RESOURCE_TRANSFORM_ERROR_RETRY_AFTER;
5149            raw.retry_after_unix_ms = *item;
5150        }
5151        Ok(raw)
5152    }
5153}
5154
5155/// Query parameters to add to the URLs of requests that match a pattern.
5156///
5157/// The library adds the parameters, in order, at the end of the URL's query and
5158/// before any fragment. It keeps the parameters that the URL already has, even
5159/// one with the same name.
5160///
5161/// See `mln_resource_transform_rule` in the
5162/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5163#[derive(Debug, Clone, PartialEq, Default)]
5164pub struct ResourceTransformRule {
5165    /// The kinds of resource that the rule covers. Zero covers every kind.
5166    pub kinds: ResourceKindFlag,
5167    pub flags: UrlMatchFlag,
5168    pub url: String,
5169    pub parameters: Vec<UrlQueryParameter>,
5170}
5171impl ToNative<sys::mln_resource_transform_rule> for ResourceTransformRule {
5172    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_resource_transform_rule> {
5173        let mut raw: sys::mln_resource_transform_rule = unsafe { std::mem::zeroed() };
5174        raw.size = std::mem::size_of::<sys::mln_resource_transform_rule>() as _;
5175        raw.kinds = to_native(&self.kinds, arena)?;
5176        raw.flags = to_native(&self.flags, arena)?;
5177        raw.url = to_native(&self.url, arena)?;
5178        raw.parameters = convert::array(&self.parameters, arena)?;
5179        raw.parameter_count = convert::count(self.parameters.len())?;
5180        Ok(raw)
5181    }
5182}
5183
5184native_enum! {
5185/// Whether a request loads a resource for a map or an offline region.
5186///
5187/// See `mln_resource_usage` in the
5188/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5189pub enum ResourceUsage: u32 {
5190    Online = 0,
5191    Offline = 1,
5192} Unknown
5193}
5194impl Default for ResourceUsage {
5195    fn default() -> Self {
5196        Self::Online
5197    }
5198}
5199
5200/// An event that a runtime or one of its maps raised.
5201///
5202/// See `mln_runtime_event` in the
5203/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5204#[derive(Debug, Clone, PartialEq)]
5205pub struct RuntimeEvent {
5206    pub r#type: RuntimeEventType,
5207    pub source_type: RuntimeEventSourceType,
5208    /// The runtime or map that raised the event, as `source_type` says.
5209    pub source: u64,
5210    /// For a map event, a map snapshot with this generation or a later one
5211    /// includes what the event reports. Zero for a runtime event.
5212    pub generation: u64,
5213    /// The error's text for an event that reports a failure, or empty.
5214    pub message: String,
5215    pub payload: RuntimeEventPayload,
5216}
5217impl FromNative<sys::mln_runtime_event> for RuntimeEvent {
5218    unsafe fn from_native(raw: sys::mln_runtime_event) -> Result<Self> {
5219        Ok(Self {
5220            r#type: RuntimeEventType::from_raw(raw.type_),
5221            source_type: RuntimeEventSourceType::from_raw(raw.source_type),
5222            source: raw.source,
5223            generation: raw.generation,
5224            message: unsafe { from_native(raw.message) }?,
5225            payload: match raw.payload_type {
5226                sys::MLN_RUNTIME_EVENT_PAYLOAD_CAMERA_CHANGE => {
5227                    RuntimeEventPayload::CameraChange(unsafe {
5228                        from_native(raw.payload.camera_change)
5229                    }?)
5230                }
5231                sys::MLN_RUNTIME_EVENT_PAYLOAD_LOADING_FAILED => {
5232                    RuntimeEventPayload::LoadingFailed(unsafe {
5233                        from_native(raw.payload.loading_failed)
5234                    }?)
5235                }
5236                sys::MLN_RUNTIME_EVENT_PAYLOAD_RENDER_FRAME => {
5237                    RuntimeEventPayload::RenderFrame(unsafe {
5238                        from_native(raw.payload.render_frame)
5239                    }?)
5240                }
5241                sys::MLN_RUNTIME_EVENT_PAYLOAD_STYLE_IMAGE => {
5242                    RuntimeEventPayload::StyleImage(unsafe {
5243                        from_native(raw.payload.style_image)
5244                    }?)
5245                }
5246                sys::MLN_RUNTIME_EVENT_PAYLOAD_TILE_ACTION => {
5247                    RuntimeEventPayload::TileAction(unsafe {
5248                        from_native(raw.payload.tile_action)
5249                    }?)
5250                }
5251                sys::MLN_RUNTIME_EVENT_PAYLOAD_SOURCE_CHANGED => {
5252                    RuntimeEventPayload::SourceChanged(unsafe {
5253                        from_native(raw.payload.source_changed)
5254                    }?)
5255                }
5256                sys::MLN_RUNTIME_EVENT_PAYLOAD_OFFLINE_REGION_STATUS => {
5257                    RuntimeEventPayload::OfflineRegionStatus(unsafe {
5258                        from_native(raw.payload.offline_region_status)
5259                    }?)
5260                }
5261                sys::MLN_RUNTIME_EVENT_PAYLOAD_OFFLINE_REGION_RESPONSE_ERROR => {
5262                    RuntimeEventPayload::OfflineRegionResponseError(unsafe {
5263                        from_native(raw.payload.offline_region_response_error)
5264                    }?)
5265                }
5266                sys::MLN_RUNTIME_EVENT_PAYLOAD_OFFLINE_REGION_TILE_COUNT_LIMIT => {
5267                    RuntimeEventPayload::OfflineRegionTileCountLimit(unsafe {
5268                        from_native(raw.payload.offline_region_tile_count_limit)
5269                    }?)
5270                }
5271                sys::MLN_RUNTIME_EVENT_PAYLOAD_GLYPHS => {
5272                    RuntimeEventPayload::Glyphs(unsafe { from_native(raw.payload.glyphs) }?)
5273                }
5274                sys::MLN_RUNTIME_EVENT_PAYLOAD_SPRITE => {
5275                    RuntimeEventPayload::Sprite(unsafe { from_native(raw.payload.sprite) }?)
5276                }
5277                sys::MLN_RUNTIME_EVENT_PAYLOAD_NONE => RuntimeEventPayload::Empty,
5278                tag => RuntimeEventPayload::Unknown(tag as u32),
5279            },
5280        })
5281    }
5282}
5283
5284/// The details of `RuntimeEventType::MapCameraWillChange` and
5285/// `RuntimeEventType::MapCameraDidChange`.
5286///
5287/// See `mln_runtime_event_camera_change` in the
5288/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5289#[derive(Debug, Clone, Copy, PartialEq, Default)]
5290pub struct RuntimeEventCameraChange {
5291    pub mode: CameraChangeMode,
5292    pub source: CameraChangeSource,
5293}
5294impl FromNative<sys::mln_runtime_event_camera_change> for RuntimeEventCameraChange {
5295    unsafe fn from_native(raw: sys::mln_runtime_event_camera_change) -> Result<Self> {
5296        Ok(Self {
5297            mode: CameraChangeMode::from_raw(raw.mode),
5298            source: CameraChangeSource::from_raw(raw.source),
5299        })
5300    }
5301}
5302
5303native_flags! {
5304/// An event type, as a bit in a set.
5305///
5306/// See `mln_runtime_event_flag` in the
5307/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5308pub struct RuntimeEventFlag: u64 {
5309    const MAP_CAMERA_WILL_CHANGE = 2;
5310    const MAP_CAMERA_IS_CHANGING = 4;
5311    const MAP_CAMERA_DID_CHANGE = 8;
5312    const MAP_STYLE_LOADED = 16;
5313    const MAP_LOADING_STARTED = 32;
5314    const MAP_LOADING_FINISHED = 64;
5315    const MAP_LOADING_FAILED = 128;
5316    const MAP_IDLE = 256;
5317    const MAP_RENDER_ERROR = 512;
5318    const MAP_RENDER_FRAME_STARTED = 1024;
5319    const MAP_RENDER_FRAME_FINISHED = 2048;
5320    const MAP_RENDER_MAP_STARTED = 4096;
5321    const MAP_RENDER_MAP_FINISHED = 8192;
5322    const MAP_STYLE_IMAGE_MISSING = 16384;
5323    const MAP_TILE_ACTION = 32768;
5324    const MAP_SOURCE_CHANGED = 65536;
5325    const OFFLINE_REGION_STATUS_CHANGED = 131072;
5326    const OFFLINE_REGION_RESPONSE_ERROR = 262144;
5327    const OFFLINE_REGION_TILE_COUNT_LIMIT_EXCEEDED = 524288;
5328    const MAP_GLYPHS_REQUESTED = 1048576;
5329    const MAP_GLYPHS_LOADED = 2097152;
5330    const MAP_GLYPHS_ERROR = 4194304;
5331    const MAP_SPRITE_REQUESTED = 8388608;
5332    const MAP_SPRITE_LOADED = 16777216;
5333    const MAP_SPRITE_ERROR = 33554432;
5334    const ALL_MAP_EVENTS = 66191358;
5335    const ALL_RUNTIME_EVENTS = 917504;
5336    const ALL = 67108862;
5337}
5338}
5339
5340/// The details of a glyph event.
5341///
5342/// The event covers the glyphs from `first` to `last`, both included.
5343///
5344/// See `mln_runtime_event_glyphs` in the
5345/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5346#[derive(Debug, Clone, PartialEq, Default)]
5347pub struct RuntimeEventGlyphs {
5348    /// The fonts that the glyphs come from, in order of preference.
5349    pub font_stack: Vec<String>,
5350    pub first: u32,
5351    pub last: u32,
5352    pub font_face: bool,
5353}
5354impl FromNative<sys::mln_runtime_event_glyphs> for RuntimeEventGlyphs {
5355    unsafe fn from_native(raw: sys::mln_runtime_event_glyphs) -> Result<Self> {
5356        Ok(Self {
5357            font_stack: unsafe { convert::copy_array(raw.font_stack, raw.font_count) }?,
5358            first: raw.first,
5359            last: raw.last,
5360            font_face: raw.font_face,
5361        })
5362    }
5363}
5364
5365/// An event callback, for `RuntimeHandle::set_event_handler()`.
5366///
5367/// See `mln_runtime_event_handler` in the
5368/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5369#[derive(Clone)]
5370pub struct RuntimeEventHandler {
5371    /// The callback receives (`events`).
5372    pub callback: std::sync::Arc<dyn Fn(Vec<RuntimeEvent>) + Send + Sync + 'static>,
5373}
5374impl std::fmt::Debug for RuntimeEventHandler {
5375    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5376        f.debug_struct("RuntimeEventHandler")
5377            .finish_non_exhaustive()
5378    }
5379}
5380impl RuntimeEventHandler {
5381    pub fn new<F>(callback: F) -> Self
5382    where
5383        F: Fn(Vec<RuntimeEvent>) + Send + Sync + 'static,
5384    {
5385        Self {
5386            callback: std::sync::Arc::new(callback),
5387        }
5388    }
5389    unsafe extern "C" fn callback_trampoline(
5390        user_data: *mut std::ffi::c_void,
5391        events: *const sys::mln_event_batch_view,
5392    ) {
5393        // SAFETY: native passes the registration that this trampoline's
5394        // descriptor transferred.
5395        let state = unsafe { callback::state::<Self>(user_data) };
5396        callback::invoke("mln_runtime_event_callback", (), || {
5397            (state.callback)({
5398                let view = unsafe { events.as_ref() }
5399                    .ok_or_else(|| Error::invalid_argument("null record value"))?;
5400                unsafe { convert::copy_strided(view.events, view.event_count, view.event_size) }?
5401            });
5402            Ok(())
5403        })
5404    }
5405}
5406impl ToNative<sys::mln_runtime_event_handler> for RuntimeEventHandler {
5407    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_runtime_event_handler> {
5408        let mut raw: sys::mln_runtime_event_handler = unsafe { std::mem::zeroed() };
5409        raw.size = std::mem::size_of::<sys::mln_runtime_event_handler>() as _;
5410        raw.callback = Some(Self::callback_trampoline as _);
5411        if !(raw.callback.is_none()) {
5412            // SAFETY: the release reclaims exactly this state.
5413            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
5414            raw.release_user_data = Some(callback::release::<Self>);
5415        }
5416        Ok(raw)
5417    }
5418}
5419
5420/// The details of `RuntimeEventType::MapLoadingFailed`.
5421///
5422/// See `mln_runtime_event_loading_failed` in the
5423/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5424#[derive(Debug, Clone, Copy, PartialEq, Default)]
5425pub struct RuntimeEventLoadingFailed {
5426    pub error: MapLoadError,
5427}
5428impl FromNative<sys::mln_runtime_event_loading_failed> for RuntimeEventLoadingFailed {
5429    unsafe fn from_native(raw: sys::mln_runtime_event_loading_failed) -> Result<Self> {
5430        Ok(Self {
5431            error: MapLoadError::from_raw(raw.error),
5432        })
5433    }
5434}
5435
5436/// The details of `RuntimeEventType::OfflineRegionResponseError`.
5437///
5438/// See `mln_runtime_event_offline_region_response_error` in the
5439/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5440#[derive(Debug, Clone, Copy, PartialEq, Default)]
5441pub struct RuntimeEventOfflineRegionResponseError {
5442    pub region_id: i64,
5443    pub reason: ResourceErrorReason,
5444}
5445impl FromNative<sys::mln_runtime_event_offline_region_response_error>
5446    for RuntimeEventOfflineRegionResponseError
5447{
5448    unsafe fn from_native(
5449        raw: sys::mln_runtime_event_offline_region_response_error,
5450    ) -> Result<Self> {
5451        Ok(Self {
5452            region_id: raw.region_id,
5453            reason: ResourceErrorReason::from_raw(raw.reason),
5454        })
5455    }
5456}
5457
5458/// The details of `RuntimeEventType::OfflineRegionStatusChanged`.
5459///
5460/// See `mln_runtime_event_offline_region_status` in the
5461/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5462#[derive(Debug, Clone, Copy, PartialEq, Default)]
5463pub struct RuntimeEventOfflineRegionStatus {
5464    pub region_id: i64,
5465    pub status: OfflineRegionStatus,
5466}
5467impl FromNative<sys::mln_runtime_event_offline_region_status> for RuntimeEventOfflineRegionStatus {
5468    unsafe fn from_native(raw: sys::mln_runtime_event_offline_region_status) -> Result<Self> {
5469        Ok(Self {
5470            region_id: raw.region_id,
5471            status: unsafe { from_native(raw.status) }?,
5472        })
5473    }
5474}
5475
5476/// The details of `RuntimeEventType::OfflineRegionTileCountLimitExceeded`.
5477///
5478/// See `mln_runtime_event_offline_region_tile_count_limit` in the
5479/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5480#[derive(Debug, Clone, Copy, PartialEq, Default)]
5481pub struct RuntimeEventOfflineRegionTileCountLimit {
5482    pub region_id: i64,
5483    /// The number of demo server tiles that the cache file's offline regions
5484    /// may hold together.
5485    pub limit: u64,
5486}
5487impl FromNative<sys::mln_runtime_event_offline_region_tile_count_limit>
5488    for RuntimeEventOfflineRegionTileCountLimit
5489{
5490    unsafe fn from_native(
5491        raw: sys::mln_runtime_event_offline_region_tile_count_limit,
5492    ) -> Result<Self> {
5493        Ok(Self {
5494            region_id: raw.region_id,
5495            limit: raw.limit,
5496        })
5497    }
5498}
5499
5500/// The details of an event, in the member that its `payload_type` names.
5501///
5502/// See `mln_runtime_event_payload` in the
5503/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5504#[derive(Debug, Clone, PartialEq)]
5505pub enum RuntimeEventPayload {
5506    CameraChange(RuntimeEventCameraChange),
5507    LoadingFailed(RuntimeEventLoadingFailed),
5508    RenderFrame(RuntimeEventRenderFrame),
5509    StyleImage(RuntimeEventStyleImage),
5510    TileAction(RuntimeEventTileAction),
5511    SourceChanged(RuntimeEventSourceChanged),
5512    OfflineRegionStatus(RuntimeEventOfflineRegionStatus),
5513    OfflineRegionResponseError(RuntimeEventOfflineRegionResponseError),
5514    OfflineRegionTileCountLimit(RuntimeEventOfflineRegionTileCountLimit),
5515    Glyphs(RuntimeEventGlyphs),
5516    Sprite(RuntimeEventSprite),
5517    Empty,
5518    Unknown(u32),
5519}
5520impl Default for RuntimeEventPayload {
5521    fn default() -> Self {
5522        Self::Unknown(0)
5523    }
5524}
5525
5526/// The details of `RuntimeEventType::MapRenderFrameFinished`.
5527///
5528/// See `mln_runtime_event_render_frame` in the
5529/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5530#[derive(Debug, Clone, Copy, PartialEq, Default)]
5531pub struct RuntimeEventRenderFrame {
5532    pub mode: RenderMode,
5533    pub needs_repaint: bool,
5534    pub placement_changed: bool,
5535    pub stats: RenderingStats,
5536}
5537impl FromNative<sys::mln_runtime_event_render_frame> for RuntimeEventRenderFrame {
5538    unsafe fn from_native(raw: sys::mln_runtime_event_render_frame) -> Result<Self> {
5539        Ok(Self {
5540            mode: RenderMode::from_raw(raw.mode),
5541            needs_repaint: raw.needs_repaint,
5542            placement_changed: raw.placement_changed,
5543            stats: unsafe { from_native(raw.stats) }?,
5544        })
5545    }
5546}
5547
5548/// The details of `RuntimeEventType::MapSourceChanged`.
5549///
5550/// See `mln_runtime_event_source_changed` in the
5551/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5552#[derive(Debug, Clone, PartialEq, Default)]
5553pub struct RuntimeEventSourceChanged {
5554    pub source_id: String,
5555}
5556impl FromNative<sys::mln_runtime_event_source_changed> for RuntimeEventSourceChanged {
5557    unsafe fn from_native(raw: sys::mln_runtime_event_source_changed) -> Result<Self> {
5558        Ok(Self {
5559            source_id: unsafe { from_native(raw.source_id) }?,
5560        })
5561    }
5562}
5563
5564native_enum! {
5565/// The kind of handle that raised an event.
5566///
5567/// See `mln_runtime_event_source_type` in the
5568/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5569pub enum RuntimeEventSourceType: u32 {
5570    Runtime = 0,
5571    Map = 1,
5572} Unknown
5573}
5574impl Default for RuntimeEventSourceType {
5575    fn default() -> Self {
5576        Self::Runtime
5577    }
5578}
5579
5580/// The details of a sprite event.
5581///
5582/// `id` and `url` are both empty when the style has no sprite.
5583///
5584/// See `mln_runtime_event_sprite` in the
5585/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5586#[derive(Debug, Clone, PartialEq, Default)]
5587pub struct RuntimeEventSprite {
5588    pub id: String,
5589    pub url: String,
5590}
5591impl FromNative<sys::mln_runtime_event_sprite> for RuntimeEventSprite {
5592    unsafe fn from_native(raw: sys::mln_runtime_event_sprite) -> Result<Self> {
5593        Ok(Self {
5594            id: unsafe { from_native(raw.id) }?,
5595            url: unsafe { from_native(raw.url) }?,
5596        })
5597    }
5598}
5599
5600/// The details of `RuntimeEventType::MapStyleImageMissing`.
5601///
5602/// See `mln_runtime_event_style_image` in the
5603/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5604#[derive(Debug, Clone, PartialEq, Default)]
5605pub struct RuntimeEventStyleImage {
5606    pub image_id: String,
5607}
5608impl FromNative<sys::mln_runtime_event_style_image> for RuntimeEventStyleImage {
5609    unsafe fn from_native(raw: sys::mln_runtime_event_style_image) -> Result<Self> {
5610        Ok(Self {
5611            image_id: unsafe { from_native(raw.image_id) }?,
5612        })
5613    }
5614}
5615
5616/// The details of `RuntimeEventType::MapTileAction`.
5617///
5618/// See `mln_runtime_event_tile_action` in the
5619/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5620#[derive(Debug, Clone, PartialEq, Default)]
5621pub struct RuntimeEventTileAction {
5622    /// The source that the tile belongs to.
5623    pub source_id: String,
5624    pub operation: TileOperation,
5625    pub tile_id: TileId,
5626}
5627impl FromNative<sys::mln_runtime_event_tile_action> for RuntimeEventTileAction {
5628    unsafe fn from_native(raw: sys::mln_runtime_event_tile_action) -> Result<Self> {
5629        Ok(Self {
5630            source_id: unsafe { from_native(raw.source_id) }?,
5631            operation: TileOperation::from_raw(raw.operation),
5632            tile_id: unsafe { from_native(raw.tile_id) }?,
5633        })
5634    }
5635}
5636
5637native_enum! {
5638/// The kind of an event.
5639///
5640/// Only maps in `MapMode::Continuous` raise
5641/// `RuntimeEventType::MapLoadingFinished`, `RuntimeEventType::MapIdle`, and the
5642/// render frame and render map events. Offline region events come only for the
5643/// regions and types that `RuntimeHandle::set_offline_region_observed()`
5644/// selects.
5645///
5646/// See `mln_runtime_event_type` in the
5647/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5648pub enum RuntimeEventType: u32 {
5649    MapCameraWillChange = 1,
5650    MapCameraIsChanging = 2,
5651    MapCameraDidChange = 3,
5652    MapStyleLoaded = 4,
5653    /// The map started to load a style.
5654    MapLoadingStarted = 5,
5655    /// The map loaded its style and everything that the current view needs, and
5656    /// rendered the result.
5657    MapLoadingFinished = 6,
5658    /// The map failed to load a style.
5659    MapLoadingFailed = 7,
5660    /// The map rendered a complete frame and has nothing left to load, animate,
5661    /// or redraw.
5662    MapIdle = 8,
5663    MapRenderError = 9,
5664    MapRenderFrameStarted = 10,
5665    MapRenderFrameFinished = 11,
5666    MapRenderMapStarted = 12,
5667    MapRenderMapFinished = 13,
5668    /// The style uses an image that it doesn't have.
5669    MapStyleImageMissing = 14,
5670    /// A tile moved to another step of loading.
5671    MapTileAction = 15,
5672    /// A source in the style changed, such as when its TileJSON loads.
5673    MapSourceChanged = 16,
5674    OfflineRegionStatusChanged = 17,
5675    /// A resource that the region needs failed to download.
5676    OfflineRegionResponseError = 18,
5677    /// The region's download became inactive because the cache file's offline
5678    /// regions hold as many tiles from MapLibre's demo tile server as the limit
5679    /// allows. Only tiles of sources with a `maplibre://` URL count toward the
5680    /// limit.
5681    OfflineRegionTileCountLimitExceeded = 19,
5682    MapGlyphsRequested = 20,
5683    MapGlyphsLoaded = 21,
5684    MapGlyphsError = 22,
5685    MapSpriteRequested = 23,
5686    MapSpriteLoaded = 24,
5687    MapSpriteError = 25,
5688} Unknown
5689}
5690
5691/// Options for `RuntimeHandle::create()`.
5692///
5693/// See `mln_runtime_options` in the
5694/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
5695#[derive(Debug, Clone, PartialEq, Default)]
5696pub struct RuntimeOptions<'a> {
5697    /// The directory that `asset://` URLs load from. Empty uses the working
5698    /// directory, or the app's assets on Android.
5699    pub asset_path: &'a str,
5700    /// The path of the cache database file, which holds the ambient cache and
5701    /// offline regions. Its directory must be writable. Empty keeps the cache
5702    /// in memory.
5703    pub cache_path: &'a str,
5704}
5705impl<'a> ToNative<sys::mln_runtime_options> for RuntimeOptions<'a> {
5706    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_runtime_options> {
5707        let mut raw: sys::mln_runtime_options = unsafe { std::mem::zeroed() };
5708        raw.size = std::mem::size_of::<sys::mln_runtime_options>() as _;
5709        raw.asset_path = to_native(&self.asset_path, arena)?;
5710        raw.cache_path = to_native(&self.cache_path, arena)?;
5711        Ok(raw)
5712    }
5713}
5714
5715/// A rectangle of the screen, from its `min` corner to its `max` corner.
5716///
5717/// See `mln_screen_box` in the
5718/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
5719#[derive(Debug, Clone, Copy, PartialEq, Default)]
5720pub struct ScreenBox {
5721    pub min: ScreenPoint,
5722    pub max: ScreenPoint,
5723}
5724impl ScreenBox {
5725    pub const fn new(min: ScreenPoint, max: ScreenPoint) -> Self {
5726        Self { min, max }
5727    }
5728}
5729impl ToNative<sys::mln_screen_box> for ScreenBox {
5730    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_screen_box> {
5731        let mut raw: sys::mln_screen_box = unsafe { std::mem::zeroed() };
5732        raw.min = to_native(&self.min, arena)?;
5733        raw.max = to_native(&self.max, arena)?;
5734        Ok(raw)
5735    }
5736}
5737
5738/// A line through points on the screen.
5739///
5740/// See `mln_screen_line_string` in the
5741/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
5742#[derive(Debug, Clone, PartialEq, Default)]
5743pub struct ScreenLineString {
5744    pub points: Vec<ScreenPoint>,
5745}
5746impl ToNative<sys::mln_screen_line_string> for ScreenLineString {
5747    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_screen_line_string> {
5748        let mut raw: sys::mln_screen_line_string = unsafe { std::mem::zeroed() };
5749        raw.points = convert::array(&self.points, arena)?;
5750        raw.point_count = convert::count(self.points.len())?;
5751        Ok(raw)
5752    }
5753}
5754
5755/// A point on the screen, in logical pixels from the map's top-left corner.
5756///
5757/// See `mln_screen_point` in the
5758/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
5759#[derive(Debug, Clone, Copy, PartialEq, Default)]
5760pub struct ScreenPoint {
5761    pub x: f64,
5762    pub y: f64,
5763}
5764impl ScreenPoint {
5765    pub const fn new(x: f64, y: f64) -> Self {
5766        Self { x, y }
5767    }
5768}
5769impl ToNative<sys::mln_screen_point> for ScreenPoint {
5770    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_screen_point> {
5771        let mut raw: sys::mln_screen_point = unsafe { std::mem::zeroed() };
5772        raw.x = self.x;
5773        raw.y = self.y;
5774        Ok(raw)
5775    }
5776}
5777impl FromNative<sys::mln_screen_point> for ScreenPoint {
5778    unsafe fn from_native(raw: sys::mln_screen_point) -> Result<Self> {
5779        Ok(Self { x: raw.x, y: raw.y })
5780    }
5781}
5782
5783/// A feature that a source feature query found.
5784///
5785/// See `mln_source_feature` in the
5786/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
5787#[derive(Debug, Clone, PartialEq, Default)]
5788pub struct SourceFeature {
5789    /// The feature, as a GeoJSON feature.
5790    pub feature: String,
5791    /// The feature's source layer, or empty when its source has none.
5792    pub source_layer_id: String,
5793}
5794impl FromNative<sys::mln_source_feature> for SourceFeature {
5795    unsafe fn from_native(raw: sys::mln_source_feature) -> Result<Self> {
5796        Ok(Self {
5797            feature: unsafe { from_native(raw.feature) }?,
5798            source_layer_id: unsafe { from_native(raw.source_layer_id) }?,
5799        })
5800    }
5801}
5802
5803/// Options for a source feature query.
5804///
5805/// See `mln_source_feature_query_options` in the
5806/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/query_8h.html).
5807#[derive(Debug, Clone, PartialEq, Default)]
5808pub struct SourceFeatureQueryOptions<'a> {
5809    /// The source layers to query. A vector source finds features only in the
5810    /// source layers named here.
5811    pub source_layer_ids: Option<&'a [&'a str]>,
5812    /// A \[filter\](https://maplibre.org/maplibre-style-spec/expressions/) that
5813    /// each feature must match. Empty matches every feature.
5814    pub filter: &'a str,
5815}
5816impl<'a> ToNative<sys::mln_source_feature_query_options> for SourceFeatureQueryOptions<'a> {
5817    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_source_feature_query_options> {
5818        let mut raw: sys::mln_source_feature_query_options = unsafe { std::mem::zeroed() };
5819        raw.size = std::mem::size_of::<sys::mln_source_feature_query_options>() as _;
5820        raw.fields = 0;
5821        if let Some(item) = &self.source_layer_ids {
5822            raw.fields |= sys::MLN_SOURCE_FEATURE_QUERY_OPTION_SOURCE_LAYER_IDS;
5823            raw.source_layer_ids = convert::array(&*item, arena)?;
5824        }
5825        raw.source_layer_id_count = convert::count(
5826            self.source_layer_ids
5827                .as_ref()
5828                .map_or(0, |items| items.len()),
5829        )?;
5830        raw.filter = to_native(&self.filter, arena)?;
5831        Ok(raw)
5832    }
5833}
5834
5835pub use crate::status::Status;
5836impl ToNative<i32> for Status {
5837    fn to_native(&self, _: &mut InputArena) -> Result<i32> {
5838        Ok(self.as_raw())
5839    }
5840}
5841impl FromNative<i32> for Status {
5842    unsafe fn from_native(raw: i32) -> Result<Self> {
5843        Ok(Self::from_raw(raw))
5844    }
5845}
5846
5847/// What a style expression's result depends on.
5848///
5849/// See `mln_style_expression_info` in the
5850/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style__expression_8h.html).
5851#[derive(Debug, Clone, Copy, PartialEq, Default)]
5852pub struct StyleExpressionInfo {
5853    /// True when the result doesn't depend on the feature or its state.
5854    pub is_feature_constant: bool,
5855    /// True when the result doesn't depend on the zoom level.
5856    pub is_zoom_constant: bool,
5857}
5858impl FromNative<sys::mln_style_expression_info> for StyleExpressionInfo {
5859    unsafe fn from_native(raw: sys::mln_style_expression_info) -> Result<Self> {
5860        Ok(Self {
5861            is_feature_constant: raw.is_feature_constant,
5862            is_zoom_constant: raw.is_zoom_constant,
5863        })
5864    }
5865}
5866
5867/// The inputs that a style expression reads while it evaluates.
5868///
5869/// See `mln_style_expression_inputs` in the
5870/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style__expression_8h.html).
5871#[derive(Debug, Clone, PartialEq, Default)]
5872pub struct StyleExpressionInputs<'a> {
5873    pub zoom: Option<f64>,
5874    /// The value of `heatmap-density`, `line-progress`, and `elevation`.
5875    pub color_ramp_parameter: Option<f64>,
5876    /// The feature to evaluate against, as a GeoJSON feature, or empty for
5877    /// none.
5878    pub feature: &'a str,
5879    /// The feature's state, as a JSON object, or empty for none.
5880    pub feature_state: &'a str,
5881    /// The values that `global-state` reads, as a JSON object, or empty for
5882    /// none.
5883    pub global_state: &'a str,
5884    /// The tile that holds the feature. `within` and `distance` need it to read
5885    /// the feature's geometry.
5886    pub canonical_tile_id: Option<CanonicalTileId>,
5887    /// The IDs of the images that `image` treats as available.
5888    pub available_images: &'a [&'a str],
5889}
5890impl<'a> ToNative<sys::mln_style_expression_inputs> for StyleExpressionInputs<'a> {
5891    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_style_expression_inputs> {
5892        let mut raw: sys::mln_style_expression_inputs = unsafe { std::mem::zeroed() };
5893        raw.size = std::mem::size_of::<sys::mln_style_expression_inputs>() as _;
5894        raw.fields = 0;
5895        if let Some(item) = &self.zoom {
5896            raw.fields |= sys::MLN_STYLE_EXPRESSION_INPUT_ZOOM;
5897            raw.zoom = *item;
5898        }
5899        if let Some(item) = &self.color_ramp_parameter {
5900            raw.fields |= sys::MLN_STYLE_EXPRESSION_INPUT_COLOR_RAMP_PARAMETER;
5901            raw.color_ramp_parameter = *item;
5902        }
5903        raw.feature = to_native(&self.feature, arena)?;
5904        raw.feature_state = to_native(&self.feature_state, arena)?;
5905        raw.global_state = to_native(&self.global_state, arena)?;
5906        if let Some(item) = &self.canonical_tile_id {
5907            raw.fields |= sys::MLN_STYLE_EXPRESSION_INPUT_CANONICAL_TILE_ID;
5908            raw.canonical_tile_id = to_native(&*item, arena)?;
5909        }
5910        raw.available_images = convert::array(&self.available_images, arena)?;
5911        raw.available_image_count = convert::count(self.available_images.len())?;
5912        Ok(raw)
5913    }
5914}
5915
5916/// Options for parsing a style expression.
5917///
5918/// See `mln_style_expression_options` in the
5919/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style__expression_8h.html).
5920#[derive(Debug, Clone, Copy, PartialEq, Default)]
5921pub struct StyleExpressionOptions {
5922    /// The type that the result must have.
5923    pub expected_type: Option<StyleExpressionType>,
5924}
5925impl ToNative<sys::mln_style_expression_options> for StyleExpressionOptions {
5926    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_style_expression_options> {
5927        let mut raw: sys::mln_style_expression_options = unsafe { std::mem::zeroed() };
5928        raw.size = std::mem::size_of::<sys::mln_style_expression_options>() as _;
5929        raw.fields = 0;
5930        if let Some(item) = &self.expected_type {
5931            raw.fields |= sys::MLN_STYLE_EXPRESSION_OPTION_EXPECTED_TYPE;
5932            raw.expected_type = to_native(&*item, arena)?;
5933        }
5934        Ok(raw)
5935    }
5936}
5937
5938/// The type of a style expression's result.
5939///
5940/// See `mln_style_expression_type` in the
5941/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style__expression_8h.html).
5942#[derive(Debug, Clone, Copy, PartialEq, Default)]
5943pub struct StyleExpressionType {
5944    pub kind: StyleExpressionTypeKind,
5945    /// The type of each item when `kind` is `StyleExpressionTypeKind::Array`.
5946    /// It can't be an array itself.
5947    pub item_kind: StyleExpressionTypeKind,
5948    /// The length of an array, or 0 for any length.
5949    pub item_count: u32,
5950}
5951impl ToNative<sys::mln_style_expression_type> for StyleExpressionType {
5952    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_style_expression_type> {
5953        let mut raw: sys::mln_style_expression_type = unsafe { std::mem::zeroed() };
5954        raw.kind = to_native(&self.kind, arena)?;
5955        raw.item_kind = to_native(&self.item_kind, arena)?;
5956        raw.item_count = self.item_count;
5957        Ok(raw)
5958    }
5959}
5960
5961native_enum! {
5962/// The type of a style expression's result, or of the items of an array result.
5963///
5964/// See `mln_style_expression_type_kind` in the
5965/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style__expression_8h.html).
5966pub enum StyleExpressionTypeKind: u32 {
5967    /// Any type.
5968    Value = 0,
5969    Number = 1,
5970    String = 2,
5971    Boolean = 3,
5972    Color = 4,
5973    Object = 5,
5974    Formatted = 6,
5975    Image = 7,
5976    Padding = 8,
5977    VariableAnchorOffsetCollection = 9,
5978    Array = 10,
5979} Unknown
5980}
5981impl Default for StyleExpressionTypeKind {
5982    fn default() -> Self {
5983        Self::Value
5984    }
5985}
5986
5987/// An image in the map's style.
5988///
5989/// See `mln_style_image_info` in the
5990/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
5991#[derive(Debug, Clone, PartialEq, Default)]
5992pub struct StyleImageInfo {
5993    pub width: u32,
5994    pub height: u32,
5995    /// The premultiplied RGBA pixels, in rows of `width` \* 4 bytes, from the
5996    /// top row down.
5997    pub pixels: Vec<u8>,
5998    pub stretch_x: Vec<ImageStretch>,
5999    pub stretch_y: Vec<ImageStretch>,
6000    pub content: Option<ImageContent>,
6001    pub text_fit_width: Option<StyleImageTextFit>,
6002    pub text_fit_height: Option<StyleImageTextFit>,
6003    pub pixel_ratio: f32,
6004    pub sdf: bool,
6005    pub keep_unused: bool,
6006}
6007impl FromNative<sys::mln_style_image_info> for StyleImageInfo {
6008    unsafe fn from_native(raw: sys::mln_style_image_info) -> Result<Self> {
6009        Ok(Self {
6010            width: raw.width,
6011            height: raw.height,
6012            pixels: unsafe { from_native(raw.pixels) }?,
6013            stretch_x: unsafe { convert::copy_array(raw.stretch_x, raw.stretch_x_count) }?,
6014            stretch_y: unsafe { convert::copy_array(raw.stretch_y, raw.stretch_y_count) }?,
6015            content: unsafe {
6016                convert::present(raw.fields, sys::MLN_STYLE_IMAGE_INFO_CONTENT, raw.content)
6017            }?,
6018            text_fit_width: if raw.fields & sys::MLN_STYLE_IMAGE_INFO_TEXT_FIT_WIDTH != 0 {
6019                Some(StyleImageTextFit::from_raw(raw.text_fit_width))
6020            } else {
6021                None
6022            },
6023            text_fit_height: if raw.fields & sys::MLN_STYLE_IMAGE_INFO_TEXT_FIT_HEIGHT != 0 {
6024                Some(StyleImageTextFit::from_raw(raw.text_fit_height))
6025            } else {
6026                None
6027            },
6028            pixel_ratio: raw.pixel_ratio,
6029            sdf: raw.sdf,
6030            keep_unused: raw.keep_unused,
6031        })
6032    }
6033}
6034
6035/// Options for a style image, as the
6036/// \[sprite\](https://maplibre.org/maplibre-style-spec/sprite/) spec describes
6037/// them.
6038///
6039/// See `mln_style_image_options` in the
6040/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6041#[derive(Debug, Clone, PartialEq, Default)]
6042pub struct StyleImageOptions {
6043    /// The ranges of columns that stretch, in increasing order without overlap.
6044    pub stretch_x: Option<Vec<ImageStretch>>,
6045    /// The ranges of rows that stretch, in increasing order without overlap.
6046    pub stretch_y: Option<Vec<ImageStretch>>,
6047    pub content: Option<ImageContent>,
6048    pub text_fit_width: Option<StyleImageTextFit>,
6049    pub text_fit_height: Option<StyleImageTextFit>,
6050    pub pixel_ratio: Option<f32>,
6051    pub sdf: Option<bool>,
6052    /// Keeps the image after no layer uses it. Without this, the map can remove
6053    /// an image that it asked for through
6054    /// `RuntimeEventType::MapStyleImageMissing`.
6055    pub keep_unused: Option<bool>,
6056}
6057impl ToNative<sys::mln_style_image_options> for StyleImageOptions {
6058    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_style_image_options> {
6059        let mut raw: sys::mln_style_image_options = unsafe { std::mem::zeroed() };
6060        raw.size = std::mem::size_of::<sys::mln_style_image_options>() as _;
6061        raw.fields = 0;
6062        if let Some(item) = &self.stretch_x {
6063            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_STRETCH_X;
6064            raw.stretch_x = convert::array(&*item, arena)?;
6065        }
6066        raw.stretch_x_count =
6067            convert::count(self.stretch_x.as_ref().map_or(0, |items| items.len()))?;
6068        if let Some(item) = &self.stretch_y {
6069            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_STRETCH_Y;
6070            raw.stretch_y = convert::array(&*item, arena)?;
6071        }
6072        raw.stretch_y_count =
6073            convert::count(self.stretch_y.as_ref().map_or(0, |items| items.len()))?;
6074        if let Some(item) = &self.content {
6075            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_CONTENT;
6076            raw.content = to_native(&*item, arena)?;
6077        }
6078        if let Some(item) = &self.text_fit_width {
6079            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_TEXT_FIT_WIDTH;
6080            raw.text_fit_width = to_native(&*item, arena)?;
6081        }
6082        if let Some(item) = &self.text_fit_height {
6083            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_TEXT_FIT_HEIGHT;
6084            raw.text_fit_height = to_native(&*item, arena)?;
6085        }
6086        if let Some(item) = &self.pixel_ratio {
6087            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_PIXEL_RATIO;
6088            raw.pixel_ratio = *item;
6089        }
6090        if let Some(item) = &self.sdf {
6091            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_SDF;
6092            raw.sdf = *item;
6093        }
6094        if let Some(item) = &self.keep_unused {
6095            raw.fields |= sys::MLN_STYLE_IMAGE_OPTION_KEEP_UNUSED;
6096            raw.keep_unused = *item;
6097        }
6098        Ok(raw)
6099    }
6100}
6101
6102native_enum! {
6103/// How an image stretches to fit text along one axis.
6104///
6105/// See `mln_style_image_text_fit` in the
6106/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6107pub enum StyleImageTextFit: u32 {
6108    StretchOrShrink = 0,
6109    StretchOnly = 1,
6110    Proportional = 2,
6111} Unknown
6112}
6113impl Default for StyleImageTextFit {
6114    fn default() -> Self {
6115        Self::StretchOrShrink
6116    }
6117}
6118
6119/// A layer in the map's style.
6120///
6121/// See `mln_style_layer_info` in the
6122/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6123#[derive(Debug, Clone, PartialEq, Default)]
6124pub struct StyleLayerInfo {
6125    pub id: String,
6126    /// The layer's
6127    /// \[type\](https://maplibre.org/maplibre-style-spec/layers/#type), such as
6128    /// `fill`.
6129    pub r#type: String,
6130    pub source_id: String,
6131    pub source_layer: String,
6132    /// The zoom level where the layer starts to show, or negative infinity when
6133    /// the layer doesn't set one.
6134    pub min_zoom: f64,
6135    /// The zoom level where the layer stops showing, or infinity when the layer
6136    /// doesn't set one.
6137    pub max_zoom: f64,
6138    pub visibility: StyleLayerVisibility,
6139}
6140impl FromNative<sys::mln_style_layer_info> for StyleLayerInfo {
6141    unsafe fn from_native(raw: sys::mln_style_layer_info) -> Result<Self> {
6142        Ok(Self {
6143            id: unsafe { from_native(raw.id) }?,
6144            r#type: unsafe { from_native(raw.type_) }?,
6145            source_id: unsafe { from_native(raw.source_id) }?,
6146            source_layer: unsafe { from_native(raw.source_layer) }?,
6147            min_zoom: raw.min_zoom,
6148            max_zoom: raw.max_zoom,
6149            visibility: StyleLayerVisibility::from_raw(raw.visibility),
6150        })
6151    }
6152}
6153
6154native_enum! {
6155/// Whether a layer shows.
6156///
6157/// See `mln_style_layer_visibility` in the
6158/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6159pub enum StyleLayerVisibility: u32 {
6160    Visible = 0,
6161    None = 1,
6162} Unknown
6163}
6164impl Default for StyleLayerVisibility {
6165    fn default() -> Self {
6166        Self::Visible
6167    }
6168}
6169
6170native_enum! {
6171/// How a raster DEM tile encodes elevation in its colors.
6172///
6173/// See `mln_style_raster_dem_encoding` in the
6174/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6175pub enum StyleRasterDemEncoding: u32 {
6176    Mapbox = 0,
6177    Terrarium = 1,
6178} Unknown
6179}
6180impl Default for StyleRasterDemEncoding {
6181    fn default() -> Self {
6182        Self::Mapbox
6183    }
6184}
6185
6186/// A source in the map's style.
6187///
6188/// See `mln_style_source_info` in the
6189/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6190#[derive(Debug, Clone, PartialEq, Default)]
6191pub struct StyleSourceInfo {
6192    pub id: String,
6193    pub r#type: StyleSourceType,
6194    pub is_volatile: bool,
6195    pub attribution: String,
6196    pub url: String,
6197    /// The tiles that the style lists in the source itself, instead of at a
6198    /// URL.
6199    pub tile_json: Option<StyleSourceTileInfo>,
6200    pub bounds: Option<LatLngBounds>,
6201    pub tile_size: Option<u32>,
6202    pub vector_encoding: Option<StyleVectorTileEncoding>,
6203    pub raster_encoding: Option<StyleRasterDemEncoding>,
6204    /// A GeoJSON source's options, with every field set.
6205    pub geo_json: Option<GeoJsonSourceOptions>,
6206}
6207impl FromNative<sys::mln_style_source_info> for StyleSourceInfo {
6208    unsafe fn from_native(raw: sys::mln_style_source_info) -> Result<Self> {
6209        Ok(Self {
6210            id: unsafe { from_native(raw.id) }?,
6211            r#type: StyleSourceType::from_raw(raw.type_),
6212            is_volatile: raw.is_volatile,
6213            attribution: unsafe { from_native(raw.attribution) }?,
6214            url: unsafe { from_native(raw.url) }?,
6215            tile_json: unsafe {
6216                convert::present(
6217                    raw.fields,
6218                    sys::MLN_STYLE_SOURCE_INFO_TILE_JSON,
6219                    raw.tile_json,
6220                )
6221            }?,
6222            bounds: unsafe {
6223                convert::present(raw.fields, sys::MLN_STYLE_SOURCE_INFO_BOUNDS, raw.bounds)
6224            }?,
6225            tile_size: (raw.fields & sys::MLN_STYLE_SOURCE_INFO_TILE_SIZE != 0)
6226                .then_some(raw.tile_size),
6227            vector_encoding: if raw.fields & sys::MLN_STYLE_SOURCE_INFO_VECTOR_ENCODING != 0 {
6228                Some(StyleVectorTileEncoding::from_raw(raw.vector_encoding))
6229            } else {
6230                None
6231            },
6232            raster_encoding: if raw.fields & sys::MLN_STYLE_SOURCE_INFO_RASTER_ENCODING != 0 {
6233                Some(StyleRasterDemEncoding::from_raw(raw.raster_encoding))
6234            } else {
6235                None
6236            },
6237            geo_json: unsafe {
6238                convert::present(
6239                    raw.fields,
6240                    sys::MLN_STYLE_SOURCE_INFO_GEO_JSON,
6241                    raw.geo_json,
6242                )
6243            }?,
6244        })
6245    }
6246}
6247
6248/// The tiles of a source, as the style lists them.
6249///
6250/// See `mln_style_source_tile_info` in the
6251/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6252#[derive(Debug, Clone, PartialEq, Default)]
6253pub struct StyleSourceTileInfo {
6254    pub tile_urls: Vec<String>,
6255    pub min_zoom: f64,
6256    pub max_zoom: f64,
6257    pub scheme: StyleTileScheme,
6258}
6259impl FromNative<sys::mln_style_source_tile_info> for StyleSourceTileInfo {
6260    unsafe fn from_native(raw: sys::mln_style_source_tile_info) -> Result<Self> {
6261        Ok(Self {
6262            tile_urls: unsafe { convert::copy_array(raw.tile_urls, raw.tile_url_count) }?,
6263            min_zoom: raw.min_zoom,
6264            max_zoom: raw.max_zoom,
6265            scheme: StyleTileScheme::from_raw(raw.scheme),
6266        })
6267    }
6268}
6269
6270native_enum! {
6271/// The type of a style source.
6272///
6273/// See `mln_style_source_type` in the
6274/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6275pub enum StyleSourceType: u32 {
6276    Unknown = 0,
6277    Vector = 1,
6278    Raster = 2,
6279    RasterDem = 3,
6280    GeoJson = 4,
6281    Image = 5,
6282    Video = 6,
6283    Annotations = 7,
6284    CustomGeometry = 8,
6285    CustomVector = 9,
6286} Unrecognized
6287}
6288impl Default for StyleSourceType {
6289    fn default() -> Self {
6290        Self::Unknown
6291    }
6292}
6293
6294native_enum! {
6295/// Whether a tileset counts tile rows from the north (XYZ) or the south (TMS).
6296///
6297/// See `mln_style_tile_scheme` in the
6298/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6299pub enum StyleTileScheme: u32 {
6300    Xyz = 0,
6301    Tms = 1,
6302} Unknown
6303}
6304impl Default for StyleTileScheme {
6305    fn default() -> Self {
6306        Self::Xyz
6307    }
6308}
6309
6310/// The default
6311/// \[transition\](https://maplibre.org/maplibre-style-spec/transition/) for
6312/// changes to a style's paint properties.
6313///
6314/// See `mln_style_transition_options` in the
6315/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6316#[derive(Debug, Clone, Copy, PartialEq, Default)]
6317pub struct StyleTransitionOptions {
6318    pub duration_ms: Option<f64>,
6319    pub delay_ms: Option<f64>,
6320    /// Whether symbols fade in and out as the map places them.
6321    pub enable_placement_transitions: Option<bool>,
6322}
6323impl ToNative<sys::mln_style_transition_options> for StyleTransitionOptions {
6324    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_style_transition_options> {
6325        let mut raw: sys::mln_style_transition_options = unsafe { std::mem::zeroed() };
6326        raw.size = std::mem::size_of::<sys::mln_style_transition_options>() as _;
6327        raw.fields = 0;
6328        if let Some(item) = &self.duration_ms {
6329            raw.fields |= sys::MLN_STYLE_TRANSITION_OPTION_DURATION;
6330            raw.duration_ms = *item;
6331        }
6332        if let Some(item) = &self.delay_ms {
6333            raw.fields |= sys::MLN_STYLE_TRANSITION_OPTION_DELAY;
6334            raw.delay_ms = *item;
6335        }
6336        if let Some(item) = &self.enable_placement_transitions {
6337            raw.fields |= sys::MLN_STYLE_TRANSITION_OPTION_ENABLE_PLACEMENT_TRANSITIONS;
6338            raw.enable_placement_transitions = *item;
6339        }
6340        Ok(raw)
6341    }
6342}
6343impl FromNative<sys::mln_style_transition_options> for StyleTransitionOptions {
6344    unsafe fn from_native(raw: sys::mln_style_transition_options) -> Result<Self> {
6345        Ok(Self {
6346            duration_ms: (raw.fields & sys::MLN_STYLE_TRANSITION_OPTION_DURATION != 0)
6347                .then_some(raw.duration_ms),
6348            delay_ms: (raw.fields & sys::MLN_STYLE_TRANSITION_OPTION_DELAY != 0)
6349                .then_some(raw.delay_ms),
6350            enable_placement_transitions: (raw.fields
6351                & sys::MLN_STYLE_TRANSITION_OPTION_ENABLE_PLACEMENT_TRANSITIONS
6352                != 0)
6353                .then_some(raw.enable_placement_transitions),
6354        })
6355    }
6356}
6357
6358native_enum! {
6359/// The format of vector tiles.
6360///
6361/// See `mln_style_vector_tile_encoding` in the
6362/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/style_8h.html).
6363pub enum StyleVectorTileEncoding: u32 {
6364    Mvt = 0,
6365    Mlt = 1,
6366} Unknown
6367}
6368impl Default for StyleVectorTileEncoding {
6369    fn default() -> Self {
6370        Self::Mvt
6371    }
6372}
6373
6374/// The layout of the pixels that `RenderSessionHandle::read_texture()` reads.
6375///
6376/// See `mln_texture_image_info` in the
6377/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6378#[derive(Debug, Clone, Copy, PartialEq, Default)]
6379pub struct TextureImageInfo {
6380    pub width: u32,
6381    pub height: u32,
6382    /// The bytes from the start of one row to the start of the next.
6383    pub stride: u32,
6384    pub byte_length: usize,
6385}
6386impl FromNative<sys::mln_texture_image_info> for TextureImageInfo {
6387    unsafe fn from_native(raw: sys::mln_texture_image_info) -> Result<Self> {
6388        Ok(Self {
6389            width: raw.width,
6390            height: raw.height,
6391            stride: raw.stride,
6392            byte_length: raw.byte_length,
6393        })
6394    }
6395}
6396
6397/// The pixels that `RenderSessionHandle::read_texture()` reads.
6398///
6399/// See `mln_texture_readback_result` in the
6400/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6401#[derive(Debug, Clone, PartialEq, Default)]
6402pub struct TextureReadbackResult {
6403    /// Premultiplied RGBA pixels with 8 bits per channel, in rows from top to
6404    /// bottom.
6405    pub data: Vec<u8>,
6406    pub info: TextureImageInfo,
6407}
6408impl FromNative<sys::mln_texture_readback_result> for TextureReadbackResult {
6409    unsafe fn from_native(raw: sys::mln_texture_readback_result) -> Result<Self> {
6410        Ok(Self {
6411            data: unsafe { from_native(raw.data) }?,
6412            info: unsafe { from_native(raw.info) }?,
6413        })
6414    }
6415}
6416
6417/// The ID of a tile.
6418///
6419/// `canonical_x` and `canonical_y` place the tile in the source's grid at zoom
6420/// `canonical_z`. `overscaled_z` is the zoom that the map draws the tile at,
6421/// and is greater when the source has no tiles that deep. `wrap` says which
6422/// copy of the world holds the tile: zero for the main one, negative to the
6423/// west, and positive to the east.
6424///
6425/// See `mln_tile_id` in the
6426/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
6427#[derive(Debug, Clone, Copy, PartialEq, Default)]
6428pub struct TileId {
6429    pub overscaled_z: u32,
6430    pub wrap: i32,
6431    pub canonical_z: u32,
6432    pub canonical_x: u32,
6433    pub canonical_y: u32,
6434}
6435impl FromNative<sys::mln_tile_id> for TileId {
6436    unsafe fn from_native(raw: sys::mln_tile_id) -> Result<Self> {
6437        Ok(Self {
6438            overscaled_z: raw.overscaled_z,
6439            wrap: raw.wrap,
6440            canonical_z: raw.canonical_z,
6441            canonical_x: raw.canonical_x,
6442            canonical_y: raw.canonical_y,
6443        })
6444    }
6445}
6446
6447native_enum! {
6448/// How the map picks the level of detail of its tiles.
6449///
6450/// See `mln_tile_lod_mode` in the
6451/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
6452pub enum TileLodMode: u32 {
6453    /// Uses the most detail at the center of the screen.
6454    Default = 0,
6455    /// Uses the most detail closest to the camera.
6456    Distance = 1,
6457} Unknown
6458}
6459impl Default for TileLodMode {
6460    fn default() -> Self {
6461        Self::Default
6462    }
6463}
6464
6465native_enum! {
6466/// A step in loading a tile.
6467///
6468/// See `mln_tile_operation` in the
6469/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
6470pub enum TileOperation: u32 {
6471    RequestedFromCache = 0,
6472    RequestedFromNetwork = 1,
6473    LoadFromNetwork = 2,
6474    LoadFromCache = 3,
6475    StartParse = 4,
6476    EndParse = 5,
6477    Error = 6,
6478    Cancelled = 7,
6479    Null = 8,
6480} Unknown
6481}
6482impl Default for TileOperation {
6483    fn default() -> Self {
6484        Self::RequestedFromCache
6485    }
6486}
6487
6488/// A timing curve from (0, 0) to (1, 1), with the control points (`x1`, `y1`)
6489/// and (`x2`, `y2`).
6490///
6491/// `x1` and `x2` are between 0 and 1.
6492///
6493/// See `mln_unit_bezier` in the
6494/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
6495#[derive(Debug, Clone, Copy, PartialEq, Default)]
6496pub struct UnitBezier {
6497    pub x1: f64,
6498    pub y1: f64,
6499    pub x2: f64,
6500    pub y2: f64,
6501}
6502impl UnitBezier {
6503    pub const fn new(x1: f64, y1: f64, x2: f64, y2: f64) -> Self {
6504        Self { x1, y1, x2, y2 }
6505    }
6506}
6507impl ToNative<sys::mln_unit_bezier> for UnitBezier {
6508    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_unit_bezier> {
6509        let mut raw: sys::mln_unit_bezier = unsafe { std::mem::zeroed() };
6510        raw.x1 = self.x1;
6511        raw.y1 = self.y1;
6512        raw.x2 = self.x2;
6513        raw.y2 = self.y2;
6514        Ok(raw)
6515    }
6516}
6517
6518native_flags! {
6519/// How a URL pattern matches a request's URL.
6520///
6521/// A pattern matches the whole URL, query included. Without flags, it matches
6522/// only the URL that equals it exactly.
6523///
6524/// See `mln_url_match_flag` in the
6525/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
6526pub struct UrlMatchFlag: u32 {
6527    /// The URL matches the pattern as a glob. `*` matches any characters except
6528    /// `/`, `**` matches any characters, and `?` matches one character except
6529    /// `/`. `\` makes the next character match only itself. For example,
6530    /// `https://*.example.com/tiles/**` matches every URL under `/tiles/` on
6531    /// each subdomain of `example.com`.
6532    const GLOB = 1;
6533}
6534}
6535
6536/// A query parameter that a resource transform rule adds to a URL.
6537///
6538/// Pass `name` and `value` unencoded. The library percent-encodes every byte of
6539/// them except the letters, digits, `-`, `.`, `_`, and `~`, and adds them as
6540/// `name=value`.
6541///
6542/// See `mln_url_query_parameter` in the
6543/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/runtime_8h.html).
6544#[derive(Debug, Clone, PartialEq)]
6545pub struct UrlQueryParameter {
6546    pub name: String,
6547    pub value: String,
6548}
6549impl UrlQueryParameter {
6550    pub fn new(name: String) -> Self {
6551        Self {
6552            name,
6553            value: Default::default(),
6554        }
6555    }
6556}
6557impl ToNative<sys::mln_url_query_parameter> for UrlQueryParameter {
6558    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_url_query_parameter> {
6559        let mut raw: sys::mln_url_query_parameter = unsafe { std::mem::zeroed() };
6560        raw.name = to_native(&self.name, arena)?;
6561        raw.value = to_native(&self.value, arena)?;
6562        Ok(raw)
6563    }
6564}
6565
6566/// A vector in three dimensions.
6567///
6568/// See `mln_vec3` in the
6569/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
6570#[derive(Debug, Clone, Copy, PartialEq, Default)]
6571pub struct Vec3 {
6572    pub x: f64,
6573    pub y: f64,
6574    pub z: f64,
6575}
6576impl Vec3 {
6577    pub const fn new(x: f64, y: f64, z: f64) -> Self {
6578        Self { x, y, z }
6579    }
6580}
6581impl ToNative<sys::mln_vec3> for Vec3 {
6582    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_vec3> {
6583        let mut raw: sys::mln_vec3 = unsafe { std::mem::zeroed() };
6584        raw.x = self.x;
6585        raw.y = self.y;
6586        raw.z = self.z;
6587        Ok(raw)
6588    }
6589}
6590impl FromNative<sys::mln_vec3> for Vec3 {
6591    unsafe fn from_native(raw: sys::mln_vec3) -> Result<Self> {
6592        Ok(Self {
6593            x: raw.x,
6594            y: raw.y,
6595            z: raw.z,
6596        })
6597    }
6598}
6599
6600native_enum! {
6601/// The vertical direction of the image that the map renders.
6602///
6603/// See `mln_viewport_mode` in the
6604/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/map_8h.html).
6605pub enum ViewportMode: u32 {
6606    Default = 0,
6607    /// Renders the image upside down.
6608    FlippedY = 1,
6609} Unknown
6610}
6611impl Default for ViewportMode {
6612    fn default() -> Self {
6613        Self::Default
6614    }
6615}
6616
6617/// A Vulkan image of a borrowed ring.
6618///
6619/// See `mln_vulkan_borrowed_texture` in the
6620/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6621#[derive(Debug, Clone, Copy, PartialEq)]
6622pub struct VulkanBorrowedTexture {
6623    /// Your VkImage.
6624    pub image: u64,
6625    /// A 2D VkImageView of `image` with one mip level and one layer.
6626    pub image_view: u64,
6627}
6628impl VulkanBorrowedTexture {
6629    pub const fn new(image: u64, image_view: u64) -> Self {
6630        Self { image, image_view }
6631    }
6632}
6633impl ToNative<sys::mln_vulkan_borrowed_texture> for VulkanBorrowedTexture {
6634    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_vulkan_borrowed_texture> {
6635        let mut raw: sys::mln_vulkan_borrowed_texture = unsafe { std::mem::zeroed() };
6636        raw.image = self.image;
6637        raw.image_view = self.image_view;
6638        Ok(raw)
6639    }
6640}
6641
6642/// A ring of your Vulkan images, for
6643/// `MapHandle::attach_vulkan_borrowed_texture()`.
6644///
6645/// `logical_size` sets the map's size. `physical_width` and `physical_height`
6646/// give the images' size in pixels, which is usually `logical_size` times the
6647/// map's scale factor. Each image must have that size, `format`, and
6648/// VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, and belong to the context's device. The
6649/// ring holds up to `TEXTURE_RING_MAX_DEPTH` distinct images.
6650///
6651/// The session uses the images until a replacement or release of the target
6652/// completes, a detach or release of the session completes, or an abandon of it
6653/// returns.
6654///
6655/// See `mln_vulkan_borrowed_texture_descriptor` in the
6656/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6657#[derive(Debug, Clone, PartialEq)]
6658pub struct VulkanBorrowedTextureDescriptor {
6659    pub logical_size: LogicalSize,
6660    pub physical_width: u32,
6661    pub physical_height: u32,
6662    pub context: VulkanContextDescriptor,
6663    pub textures: Vec<VulkanBorrowedTexture>,
6664    /// The images' VkFormat.
6665    pub format: u32,
6666    /// The VkImageLayout that each frame leaves its image in.
6667    pub final_layout: u32,
6668    pub owner: VulkanImageOwner,
6669}
6670impl VulkanBorrowedTextureDescriptor {
6671    pub fn new(
6672        logical_size: LogicalSize,
6673        physical_width: u32,
6674        physical_height: u32,
6675        context: VulkanContextDescriptor,
6676        textures: Vec<VulkanBorrowedTexture>,
6677        format: u32,
6678        final_layout: u32,
6679    ) -> Self {
6680        Self {
6681            logical_size,
6682            physical_width,
6683            physical_height,
6684            context,
6685            textures,
6686            format,
6687            final_layout,
6688            owner: Default::default(),
6689        }
6690    }
6691}
6692impl ToNative<sys::mln_vulkan_borrowed_texture_descriptor> for VulkanBorrowedTextureDescriptor {
6693    fn to_native(
6694        &self,
6695        arena: &mut InputArena,
6696    ) -> Result<sys::mln_vulkan_borrowed_texture_descriptor> {
6697        let mut raw: sys::mln_vulkan_borrowed_texture_descriptor = unsafe { std::mem::zeroed() };
6698        raw.size = std::mem::size_of::<sys::mln_vulkan_borrowed_texture_descriptor>() as _;
6699        raw.logical_size = to_native(&self.logical_size, arena)?;
6700        raw.physical_width = self.physical_width;
6701        raw.physical_height = self.physical_height;
6702        raw.context = to_native(&self.context, arena)?;
6703        raw.textures = convert::array(&self.textures, arena)?;
6704        raw.texture_count = convert::count(self.textures.len())?;
6705        raw.format = self.format;
6706        raw.final_layout = self.final_layout;
6707        raw.owner = to_native(&self.owner, arena)?;
6708        Ok(raw)
6709    }
6710}
6711
6712/// New Vulkan images for a borrowed ring, for
6713/// `RenderSessionHandle::set_vulkan_borrowed_texture_target()`.
6714///
6715/// The members and the images follow the rules of
6716/// `VulkanBorrowedTextureDescriptor`. The ring keeps its depth, context,
6717/// `format`, `final_layout`, and `owner`, so give it as many images as it
6718/// attached with, in that format, on the same device.
6719///
6720/// See `mln_vulkan_borrowed_texture_replacement` in the
6721/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6722#[derive(Debug, Clone, PartialEq)]
6723pub struct VulkanBorrowedTextureReplacement {
6724    pub logical_size: LogicalSize,
6725    pub physical_width: u32,
6726    pub physical_height: u32,
6727    pub textures: Vec<VulkanBorrowedTexture>,
6728}
6729impl VulkanBorrowedTextureReplacement {
6730    pub fn new(
6731        logical_size: LogicalSize,
6732        physical_width: u32,
6733        physical_height: u32,
6734        textures: Vec<VulkanBorrowedTexture>,
6735    ) -> Self {
6736        Self {
6737            logical_size,
6738            physical_width,
6739            physical_height,
6740            textures,
6741        }
6742    }
6743}
6744impl ToNative<sys::mln_vulkan_borrowed_texture_replacement> for VulkanBorrowedTextureReplacement {
6745    fn to_native(
6746        &self,
6747        arena: &mut InputArena,
6748    ) -> Result<sys::mln_vulkan_borrowed_texture_replacement> {
6749        let mut raw: sys::mln_vulkan_borrowed_texture_replacement = unsafe { std::mem::zeroed() };
6750        raw.size = std::mem::size_of::<sys::mln_vulkan_borrowed_texture_replacement>() as _;
6751        raw.logical_size = to_native(&self.logical_size, arena)?;
6752        raw.physical_width = self.physical_width;
6753        raw.physical_height = self.physical_height;
6754        raw.textures = convert::array(&self.textures, arena)?;
6755        raw.texture_count = convert::count(self.textures.len())?;
6756        Ok(raw)
6757    }
6758}
6759
6760/// The Vulkan device and queue that a render session uses.
6761///
6762/// Keep these objects alive until a detach or release of the session completes,
6763/// or an abandon of it returns.
6764///
6765/// See `mln_vulkan_context_descriptor` in the
6766/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
6767#[derive(Debug, Clone, Copy, PartialEq)]
6768pub struct VulkanContextDescriptor {
6769    /// A `VkInstance`.
6770    pub instance: *mut std::ffi::c_void,
6771    /// A `VkPhysicalDevice`.
6772    pub physical_device: *mut std::ffi::c_void,
6773    /// A `VkDevice`.
6774    pub device: *mut std::ffi::c_void,
6775    /// A `VkQueue` from `graphics_queue_family_index` that supports graphics.
6776    /// If you submit to it too, set `RenderSessionAttachOptions::queue_lock`.
6777    pub graphics_queue: *mut std::ffi::c_void,
6778    pub graphics_queue_family_index: u32,
6779    /// Your `vkGetInstanceProcAddr`, or null to use the Vulkan loader's.
6780    pub get_instance_proc_addr: *mut std::ffi::c_void,
6781    /// Your `vkGetDeviceProcAddr`, or null to look it up from the instance.
6782    pub get_device_proc_addr: *mut std::ffi::c_void,
6783}
6784impl VulkanContextDescriptor {
6785    pub fn new(
6786        instance: *mut std::ffi::c_void,
6787        physical_device: *mut std::ffi::c_void,
6788        device: *mut std::ffi::c_void,
6789        graphics_queue: *mut std::ffi::c_void,
6790    ) -> Self {
6791        Self {
6792            instance,
6793            physical_device,
6794            device,
6795            graphics_queue,
6796            graphics_queue_family_index: Default::default(),
6797            get_instance_proc_addr: Default::default(),
6798            get_device_proc_addr: Default::default(),
6799        }
6800    }
6801}
6802impl ToNative<sys::mln_vulkan_context_descriptor> for VulkanContextDescriptor {
6803    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_vulkan_context_descriptor> {
6804        let mut raw: sys::mln_vulkan_context_descriptor = unsafe { std::mem::zeroed() };
6805        raw.instance = self.instance;
6806        raw.physical_device = self.physical_device;
6807        raw.device = self.device;
6808        raw.graphics_queue = self.graphics_queue;
6809        raw.graphics_queue_family_index = self.graphics_queue_family_index;
6810        raw.get_instance_proc_addr = self.get_instance_proc_addr;
6811        raw.get_device_proc_addr = self.get_device_proc_addr;
6812        Ok(raw)
6813    }
6814}
6815impl FromNative<sys::mln_vulkan_context_descriptor> for VulkanContextDescriptor {
6816    unsafe fn from_native(raw: sys::mln_vulkan_context_descriptor) -> Result<Self> {
6817        Ok(Self {
6818            instance: raw.instance,
6819            physical_device: raw.physical_device,
6820            device: raw.device,
6821            graphics_queue: raw.graphics_queue,
6822            graphics_queue_family_index: raw.graphics_queue_family_index,
6823            get_instance_proc_addr: raw.get_instance_proc_addr,
6824            get_device_proc_addr: raw.get_device_proc_addr,
6825        })
6826    }
6827}
6828
6829/// A Vulkan device's context, as `VulkanDeviceHandle::get_context()` reports
6830/// it.
6831///
6832/// See `mln_vulkan_device_context_result` in the
6833/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/vulkan_8h.html).
6834#[derive(Debug, Clone, Copy, PartialEq)]
6835pub struct VulkanDeviceContextResult {
6836    pub context: VulkanContextDescriptor,
6837}
6838impl FromNative<sys::mln_vulkan_device_context_result> for VulkanDeviceContextResult {
6839    unsafe fn from_native(raw: sys::mln_vulkan_device_context_result) -> Result<Self> {
6840        Ok(Self {
6841            context: unsafe { from_native(raw.context) }?,
6842        })
6843    }
6844}
6845
6846/// Options for `VulkanDeviceHandle::create()`.
6847///
6848/// See `mln_vulkan_device_options` in the
6849/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/vulkan_8h.html).
6850#[derive(Debug, Clone, PartialEq, Default)]
6851pub struct VulkanDeviceOptions<'a> {
6852    /// Whether the device can present to a window. The instance then enables
6853    /// VK_KHR_surface and the platform's surface extensions, and the device
6854    /// enables VK_KHR_swapchain. Defaults to false.
6855    pub presentation: Option<bool>,
6856    /// The 16-byte `deviceUUID` of the GPU to use, as
6857    /// `VkPhysicalDeviceIDProperties` reports it.
6858    pub device_uuid: Option<&'a [u8]>,
6859    /// The 8-byte `deviceLUID` of the GPU to use, as
6860    /// `VkPhysicalDeviceIDProperties` reports it. On Windows, this is the GPU's
6861    /// DXGI adapter LUID.
6862    pub device_luid: Option<&'a [u8]>,
6863}
6864impl<'a> ToNative<sys::mln_vulkan_device_options> for VulkanDeviceOptions<'a> {
6865    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_vulkan_device_options> {
6866        let mut raw: sys::mln_vulkan_device_options = unsafe { std::mem::zeroed() };
6867        raw.size = std::mem::size_of::<sys::mln_vulkan_device_options>() as _;
6868        raw.fields = 0;
6869        if let Some(item) = &self.presentation {
6870            raw.fields |= sys::MLN_VULKAN_DEVICE_OPTION_PRESENTATION;
6871            raw.presentation = *item;
6872        }
6873        if let Some(item) = &self.device_uuid {
6874            raw.fields |= sys::MLN_VULKAN_DEVICE_OPTION_DEVICE_UUID;
6875            raw.device_uuid = to_native(&*item, arena)?;
6876        }
6877        if let Some(item) = &self.device_luid {
6878            raw.fields |= sys::MLN_VULKAN_DEVICE_OPTION_DEVICE_LUID;
6879            raw.device_luid = to_native(&*item, arena)?;
6880        }
6881        Ok(raw)
6882    }
6883}
6884
6885native_enum! {
6886/// The queue family that a borrowed image goes to after each frame.
6887///
6888/// With `VulkanImageOwner::External` or `VulkanImageOwner::Foreign`, acquire
6889/// the image on your side before you read it. You don't need to release it
6890/// back.
6891///
6892/// See `mln_vulkan_image_owner` in the
6893/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6894pub enum VulkanImageOwner: u32 {
6895    /// The image stays with the queue family of `graphics_queue_family_index`.
6896    GraphicsQueue = 0,
6897    /// Each frame releases the image to VK_QUEUE_FAMILY_EXTERNAL.
6898    External = 1,
6899    /// Each frame releases the image to VK_QUEUE_FAMILY_FOREIGN_EXT.
6900    Foreign = 2,
6901} Unknown
6902}
6903impl Default for VulkanImageOwner {
6904    fn default() -> Self {
6905        Self::GraphicsQueue
6906    }
6907}
6908
6909/// A Vulkan surface to present to, for `MapHandle::attach_vulkan_surface()`.
6910///
6911/// The device must have VK_KHR_swapchain enabled, and the queue family of
6912/// `graphics_queue_family_index` must support presenting to the surface. The
6913/// session creates the swapchain. It uses the surface until a replacement or
6914/// release of the target completes, a detach or release of the session
6915/// completes, or an abandon of it returns.
6916///
6917/// See `mln_vulkan_surface_descriptor` in the
6918/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
6919#[derive(Debug, Clone, Copy, PartialEq)]
6920pub struct VulkanSurfaceDescriptor {
6921    pub logical_size: LogicalSize,
6922    pub context: VulkanContextDescriptor,
6923    /// Your VkSurfaceKHR.
6924    pub surface: u64,
6925}
6926impl VulkanSurfaceDescriptor {
6927    pub fn new(logical_size: LogicalSize, context: VulkanContextDescriptor, surface: u64) -> Self {
6928        Self {
6929            logical_size,
6930            context,
6931            surface,
6932        }
6933    }
6934}
6935impl ToNative<sys::mln_vulkan_surface_descriptor> for VulkanSurfaceDescriptor {
6936    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_vulkan_surface_descriptor> {
6937        let mut raw: sys::mln_vulkan_surface_descriptor = unsafe { std::mem::zeroed() };
6938        raw.size = std::mem::size_of::<sys::mln_vulkan_surface_descriptor>() as _;
6939        raw.logical_size = to_native(&self.logical_size, arena)?;
6940        raw.context = to_native(&self.context, arena)?;
6941        raw.surface = self.surface;
6942        Ok(raw)
6943    }
6944}
6945
6946/// A new Vulkan surface for `RenderSessionHandle::set_vulkan_surface_target()`.
6947///
6948/// The session presents to it with the context that it attached with, so the
6949/// queue family of that context's `graphics_queue_family_index` must support
6950/// presenting to the surface. It uses the surface until a replacement or
6951/// release of the target completes, a detach or release of the session
6952/// completes, or an abandon of it returns.
6953///
6954/// See `mln_vulkan_surface_replacement` in the
6955/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
6956#[derive(Debug, Clone, Copy, PartialEq)]
6957pub struct VulkanSurfaceReplacement {
6958    pub logical_size: LogicalSize,
6959    /// Your VkSurfaceKHR.
6960    pub surface: u64,
6961}
6962impl VulkanSurfaceReplacement {
6963    pub const fn new(logical_size: LogicalSize, surface: u64) -> Self {
6964        Self {
6965            logical_size,
6966            surface,
6967        }
6968    }
6969}
6970impl ToNative<sys::mln_vulkan_surface_replacement> for VulkanSurfaceReplacement {
6971    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_vulkan_surface_replacement> {
6972        let mut raw: sys::mln_vulkan_surface_replacement = unsafe { std::mem::zeroed() };
6973        raw.size = std::mem::size_of::<sys::mln_vulkan_surface_replacement>() as _;
6974        raw.logical_size = to_native(&self.logical_size, arena)?;
6975        raw.surface = self.surface;
6976        Ok(raw)
6977    }
6978}
6979
6980/// The Vulkan image of an acquired frame.
6981///
6982/// See `mln_vulkan_texture_frame` in the
6983/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
6984#[derive(Debug, Clone, Copy, PartialEq, Default)]
6985pub struct VulkanTextureFrame {
6986    pub width: u32,
6987    pub height: u32,
6988    pub scale_factor: f64,
6989    /// The image's index in the descriptor's `textures`.
6990    pub slot: u32,
6991    /// The VkImage.
6992    pub image: u64,
6993    /// The VkImageView.
6994    pub image_view: u64,
6995    /// The image's VkDevice.
6996    pub device: *mut std::ffi::c_void,
6997    /// The image's VkFormat.
6998    pub format: u32,
6999    /// The VkImageLayout that the frame left the image in.
7000    pub layout: u32,
7001}
7002impl FromNative<sys::mln_vulkan_texture_frame> for VulkanTextureFrame {
7003    unsafe fn from_native(raw: sys::mln_vulkan_texture_frame) -> Result<Self> {
7004        Ok(Self {
7005            width: raw.width,
7006            height: raw.height,
7007            scale_factor: raw.scale_factor,
7008            slot: raw.slot,
7009            image: raw.image,
7010            image_view: raw.image_view,
7011            device: raw.device,
7012            format: raw.format,
7013            layout: raw.layout,
7014        })
7015    }
7016}
7017
7018/// A callback that tells the caller when work is ready.
7019///
7020/// Can run on any thread, including the caller's own thread during a library
7021/// call. Return quickly and don't block.
7022///
7023/// See `mln_wake` in the
7024/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/wake_8h.html).
7025#[derive(Clone, Default)]
7026pub struct Wake {
7027    /// Null to turn the wake off.
7028    pub callback: Option<std::sync::Arc<dyn Fn() + Send + Sync + 'static>>,
7029}
7030impl std::fmt::Debug for Wake {
7031    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7032        f.debug_struct("Wake").finish_non_exhaustive()
7033    }
7034}
7035impl Wake {
7036    pub fn with_callback<F>(mut self, callback: F) -> Self
7037    where
7038        F: Fn() + Send + Sync + 'static,
7039    {
7040        self.callback = Some(std::sync::Arc::new(callback));
7041        self
7042    }
7043    pub fn new<F>(callback: F) -> Self
7044    where
7045        F: Fn() + Send + Sync + 'static,
7046    {
7047        Self::default().with_callback(callback)
7048    }
7049    unsafe extern "C" fn callback_trampoline(user_data: *mut std::ffi::c_void) {
7050        // SAFETY: native passes the registration that this trampoline's
7051        // descriptor transferred.
7052        let state = unsafe { callback::state::<Self>(user_data) };
7053        callback::invoke("mln_wake_callback", (), || {
7054            callback::require(&state.callback)?();
7055            Ok(())
7056        })
7057    }
7058}
7059impl ToNative<sys::mln_wake> for Wake {
7060    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_wake> {
7061        let mut raw: sys::mln_wake = unsafe { std::mem::zeroed() };
7062        raw.callback = self
7063            .callback
7064            .as_ref()
7065            .map(|_| Self::callback_trampoline as _);
7066        if !(raw.callback.is_none()) {
7067            // SAFETY: the release reclaims exactly this state.
7068            raw.user_data = unsafe { arena.registration(self.clone(), callback::release::<Self>) };
7069            raw.release_user_data = Some(callback::release::<Self>);
7070        }
7071        Ok(raw)
7072    }
7073}
7074
7075/// A Wayland surface to present to, for `MapHandle::attach_wayland_surface()`.
7076///
7077/// See `mln_wayland_surface_descriptor` in the
7078/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/wayland_8h.html).
7079#[derive(Debug, Clone, Copy, PartialEq)]
7080pub struct WaylandSurfaceDescriptor {
7081    pub logical_size: LogicalSize,
7082    /// Your `wl_display*`.
7083    pub display: *mut std::ffi::c_void,
7084    /// Your `wl_surface*`, on `display`.
7085    pub surface: *mut std::ffi::c_void,
7086}
7087impl WaylandSurfaceDescriptor {
7088    pub fn new(
7089        logical_size: LogicalSize,
7090        display: *mut std::ffi::c_void,
7091        surface: *mut std::ffi::c_void,
7092    ) -> Self {
7093        Self {
7094            logical_size,
7095            display,
7096            surface,
7097        }
7098    }
7099}
7100impl ToNative<sys::mln_wayland_surface_descriptor> for WaylandSurfaceDescriptor {
7101    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_wayland_surface_descriptor> {
7102        let mut raw: sys::mln_wayland_surface_descriptor = unsafe { std::mem::zeroed() };
7103        raw.size = std::mem::size_of::<sys::mln_wayland_surface_descriptor>() as _;
7104        raw.logical_size = to_native(&self.logical_size, arena)?;
7105        raw.display = self.display;
7106        raw.surface = self.surface;
7107        Ok(raw)
7108    }
7109}
7110
7111/// A new Wayland surface for
7112/// `RenderSessionHandle::set_wayland_surface_target()`.
7113///
7114/// See `mln_wayland_surface_replacement` in the
7115/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/wayland_8h.html).
7116#[derive(Debug, Clone, Copy, PartialEq)]
7117pub struct WaylandSurfaceReplacement {
7118    pub logical_size: LogicalSize,
7119    /// Your `wl_surface*`, on the display that the session attached with.
7120    pub surface: *mut std::ffi::c_void,
7121}
7122impl WaylandSurfaceReplacement {
7123    pub fn new(logical_size: LogicalSize, surface: *mut std::ffi::c_void) -> Self {
7124        Self {
7125            logical_size,
7126            surface,
7127        }
7128    }
7129}
7130impl ToNative<sys::mln_wayland_surface_replacement> for WaylandSurfaceReplacement {
7131    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_wayland_surface_replacement> {
7132        let mut raw: sys::mln_wayland_surface_replacement = unsafe { std::mem::zeroed() };
7133        raw.size = std::mem::size_of::<sys::mln_wayland_surface_replacement>() as _;
7134        raw.logical_size = to_native(&self.logical_size, arena)?;
7135        raw.surface = self.surface;
7136        Ok(raw)
7137    }
7138}
7139
7140/// The WebGL context or canvas that a render session uses.
7141///
7142/// See `mln_web_gl_context_descriptor` in the
7143/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7144#[derive(Debug, Clone, PartialEq, Default)]
7145pub struct WebGlContextDescriptor<'a> {
7146    pub kind: WebGlContextKind,
7147    /// Your `EMSCRIPTEN_WEBGL_CONTEXT_HANDLE`, for an existing context.
7148    pub context: i32,
7149    /// The canvas's CSS selector, for a transferred canvas.
7150    pub canvas_selector: &'a str,
7151}
7152impl<'a> ToNative<sys::mln_web_gl_context_descriptor> for WebGlContextDescriptor<'a> {
7153    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_web_gl_context_descriptor> {
7154        let mut raw: sys::mln_web_gl_context_descriptor = unsafe { std::mem::zeroed() };
7155        raw.kind = to_native(&self.kind, arena)?;
7156        raw.context = self.context;
7157        raw.canvas_selector = to_native(&self.canvas_selector, arena)?;
7158        Ok(raw)
7159    }
7160}
7161
7162native_enum! {
7163/// How a render session gets its WebGL context.
7164///
7165/// See `mln_web_gl_context_kind` in the
7166/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7167pub enum WebGlContextKind: u32 {
7168    /// The session uses a context that you created with
7169    /// `emscripten_webgl_create_context()`.
7170    Existing = 0,
7171    /// The library transfers the canvas that `canvas_selector` names to a
7172    /// worker and creates the context there.
7173    TransferredCanvas = 1,
7174} Unknown
7175}
7176impl Default for WebGlContextKind {
7177    fn default() -> Self {
7178        Self::Existing
7179    }
7180}
7181
7182/// A WebGPU texture of a borrowed ring.
7183///
7184/// See `mln_web_gpu_borrowed_texture` in the
7185/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
7186#[derive(Debug, Clone, Copy, PartialEq)]
7187pub struct WebGpuBorrowedTexture {
7188    /// Your WGPUTexture.
7189    pub texture: *mut std::ffi::c_void,
7190    /// A WGPUTextureView of `texture`.
7191    pub texture_view: *mut std::ffi::c_void,
7192}
7193impl WebGpuBorrowedTexture {
7194    pub fn new(texture: *mut std::ffi::c_void, texture_view: *mut std::ffi::c_void) -> Self {
7195        Self {
7196            texture,
7197            texture_view,
7198        }
7199    }
7200}
7201impl ToNative<sys::mln_web_gpu_borrowed_texture> for WebGpuBorrowedTexture {
7202    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_web_gpu_borrowed_texture> {
7203        let mut raw: sys::mln_web_gpu_borrowed_texture = unsafe { std::mem::zeroed() };
7204        raw.texture = self.texture;
7205        raw.texture_view = self.texture_view;
7206        Ok(raw)
7207    }
7208}
7209
7210/// A ring of your WebGPU textures, for
7211/// `MapHandle::attach_web_gpu_borrowed_texture()`.
7212///
7213/// `logical_size` sets the map's size. `physical_width` and `physical_height`
7214/// give the textures' size in pixels, which is usually `logical_size` times the
7215/// map's scale factor. Each texture must be 2D with that size, `format`, one
7216/// layer, one mip level, one sample, and WGPUTextureUsage_RenderAttachment. The
7217/// ring holds up to `TEXTURE_RING_MAX_DEPTH` distinct textures.
7218///
7219/// The session uses the textures until a replacement or release of the target
7220/// completes, a detach or release of the session completes, or an abandon of it
7221/// returns.
7222///
7223/// See `mln_web_gpu_borrowed_texture_descriptor` in the
7224/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
7225#[derive(Debug, Clone, PartialEq)]
7226pub struct WebGpuBorrowedTextureDescriptor {
7227    pub logical_size: LogicalSize,
7228    pub physical_width: u32,
7229    pub physical_height: u32,
7230    pub context: WebGpuContextDescriptor,
7231    pub textures: Vec<WebGpuBorrowedTexture>,
7232    /// The textures' WGPUTextureFormat.
7233    pub format: u32,
7234}
7235impl WebGpuBorrowedTextureDescriptor {
7236    pub fn new(
7237        logical_size: LogicalSize,
7238        physical_width: u32,
7239        physical_height: u32,
7240        context: WebGpuContextDescriptor,
7241        textures: Vec<WebGpuBorrowedTexture>,
7242        format: u32,
7243    ) -> Self {
7244        Self {
7245            logical_size,
7246            physical_width,
7247            physical_height,
7248            context,
7249            textures,
7250            format,
7251        }
7252    }
7253}
7254impl ToNative<sys::mln_web_gpu_borrowed_texture_descriptor> for WebGpuBorrowedTextureDescriptor {
7255    fn to_native(
7256        &self,
7257        arena: &mut InputArena,
7258    ) -> Result<sys::mln_web_gpu_borrowed_texture_descriptor> {
7259        let mut raw: sys::mln_web_gpu_borrowed_texture_descriptor = unsafe { std::mem::zeroed() };
7260        raw.size = std::mem::size_of::<sys::mln_web_gpu_borrowed_texture_descriptor>() as _;
7261        raw.logical_size = to_native(&self.logical_size, arena)?;
7262        raw.physical_width = self.physical_width;
7263        raw.physical_height = self.physical_height;
7264        raw.context = to_native(&self.context, arena)?;
7265        raw.textures = convert::array(&self.textures, arena)?;
7266        raw.texture_count = convert::count(self.textures.len())?;
7267        raw.format = self.format;
7268        Ok(raw)
7269    }
7270}
7271
7272/// New WebGPU textures for a borrowed ring, for
7273/// `RenderSessionHandle::set_web_gpu_borrowed_texture_target()`.
7274///
7275/// The members and the textures follow the rules of
7276/// `WebGpuBorrowedTextureDescriptor`. The ring keeps its depth, context, and
7277/// `format`, so give it as many textures as it attached with, in that format,
7278/// on the same device.
7279///
7280/// See `mln_web_gpu_borrowed_texture_replacement` in the
7281/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
7282#[derive(Debug, Clone, PartialEq)]
7283pub struct WebGpuBorrowedTextureReplacement {
7284    pub logical_size: LogicalSize,
7285    pub physical_width: u32,
7286    pub physical_height: u32,
7287    pub textures: Vec<WebGpuBorrowedTexture>,
7288}
7289impl WebGpuBorrowedTextureReplacement {
7290    pub fn new(
7291        logical_size: LogicalSize,
7292        physical_width: u32,
7293        physical_height: u32,
7294        textures: Vec<WebGpuBorrowedTexture>,
7295    ) -> Self {
7296        Self {
7297            logical_size,
7298            physical_width,
7299            physical_height,
7300            textures,
7301        }
7302    }
7303}
7304impl ToNative<sys::mln_web_gpu_borrowed_texture_replacement> for WebGpuBorrowedTextureReplacement {
7305    fn to_native(
7306        &self,
7307        arena: &mut InputArena,
7308    ) -> Result<sys::mln_web_gpu_borrowed_texture_replacement> {
7309        let mut raw: sys::mln_web_gpu_borrowed_texture_replacement = unsafe { std::mem::zeroed() };
7310        raw.size = std::mem::size_of::<sys::mln_web_gpu_borrowed_texture_replacement>() as _;
7311        raw.logical_size = to_native(&self.logical_size, arena)?;
7312        raw.physical_width = self.physical_width;
7313        raw.physical_height = self.physical_height;
7314        raw.textures = convert::array(&self.textures, arena)?;
7315        raw.texture_count = convert::count(self.textures.len())?;
7316        Ok(raw)
7317    }
7318}
7319
7320/// The WebGPU device that a render session uses.
7321///
7322/// See `mln_web_gpu_context_descriptor` in the
7323/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7324#[derive(Debug, Clone, Copy, PartialEq)]
7325pub struct WebGpuContextDescriptor {
7326    /// A `WGPUInstance`, or null.
7327    pub instance: *mut std::ffi::c_void,
7328    /// A `WGPUDevice`.
7329    pub device: *mut std::ffi::c_void,
7330    /// A `WGPUQueue`, or null to use the device's queue.
7331    pub queue: *mut std::ffi::c_void,
7332}
7333impl WebGpuContextDescriptor {
7334    pub fn new(device: *mut std::ffi::c_void) -> Self {
7335        Self {
7336            instance: Default::default(),
7337            device,
7338            queue: Default::default(),
7339        }
7340    }
7341}
7342impl ToNative<sys::mln_web_gpu_context_descriptor> for WebGpuContextDescriptor {
7343    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_web_gpu_context_descriptor> {
7344        let mut raw: sys::mln_web_gpu_context_descriptor = unsafe { std::mem::zeroed() };
7345        raw.instance = self.instance;
7346        raw.device = self.device;
7347        raw.queue = self.queue;
7348        Ok(raw)
7349    }
7350}
7351
7352/// A WebGPU surface to present to, for `MapHandle::attach_web_gpu_surface()`.
7353///
7354/// The session configures the surface. It uses the surface until a replacement
7355/// or release of the target completes, a detach or release of the session
7356/// completes, or an abandon of it returns.
7357///
7358/// See `mln_web_gpu_surface_descriptor` in the
7359/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
7360#[derive(Debug, Clone, Copy, PartialEq)]
7361pub struct WebGpuSurfaceDescriptor {
7362    pub logical_size: LogicalSize,
7363    pub context: WebGpuContextDescriptor,
7364    /// Your WGPUSurface.
7365    pub surface: *mut std::ffi::c_void,
7366    /// The WGPUTextureFormat to configure the surface with.
7367    pub format: u32,
7368}
7369impl WebGpuSurfaceDescriptor {
7370    pub fn new(
7371        logical_size: LogicalSize,
7372        context: WebGpuContextDescriptor,
7373        surface: *mut std::ffi::c_void,
7374        format: u32,
7375    ) -> Self {
7376        Self {
7377            logical_size,
7378            context,
7379            surface,
7380            format,
7381        }
7382    }
7383}
7384impl ToNative<sys::mln_web_gpu_surface_descriptor> for WebGpuSurfaceDescriptor {
7385    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_web_gpu_surface_descriptor> {
7386        let mut raw: sys::mln_web_gpu_surface_descriptor = unsafe { std::mem::zeroed() };
7387        raw.size = std::mem::size_of::<sys::mln_web_gpu_surface_descriptor>() as _;
7388        raw.logical_size = to_native(&self.logical_size, arena)?;
7389        raw.context = to_native(&self.context, arena)?;
7390        raw.surface = self.surface;
7391        raw.format = self.format;
7392        Ok(raw)
7393    }
7394}
7395
7396/// A new WebGPU surface for
7397/// `RenderSessionHandle::set_web_gpu_surface_target()`.
7398///
7399/// The session configures it with the context and format that it attached with.
7400/// It uses the surface until a replacement or release of the target completes,
7401/// a detach or release of the session completes, or an abandon of it returns.
7402///
7403/// See `mln_web_gpu_surface_replacement` in the
7404/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/surface_8h.html).
7405#[derive(Debug, Clone, Copy, PartialEq)]
7406pub struct WebGpuSurfaceReplacement {
7407    pub logical_size: LogicalSize,
7408    /// Your WGPUSurface.
7409    pub surface: *mut std::ffi::c_void,
7410}
7411impl WebGpuSurfaceReplacement {
7412    pub fn new(logical_size: LogicalSize, surface: *mut std::ffi::c_void) -> Self {
7413        Self {
7414            logical_size,
7415            surface,
7416        }
7417    }
7418}
7419impl ToNative<sys::mln_web_gpu_surface_replacement> for WebGpuSurfaceReplacement {
7420    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_web_gpu_surface_replacement> {
7421        let mut raw: sys::mln_web_gpu_surface_replacement = unsafe { std::mem::zeroed() };
7422        raw.size = std::mem::size_of::<sys::mln_web_gpu_surface_replacement>() as _;
7423        raw.logical_size = to_native(&self.logical_size, arena)?;
7424        raw.surface = self.surface;
7425        Ok(raw)
7426    }
7427}
7428
7429/// The WebGPU texture of an acquired frame.
7430///
7431/// See `mln_web_gpu_texture_frame` in the
7432/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/texture_8h.html).
7433#[derive(Debug, Clone, Copy, PartialEq, Default)]
7434pub struct WebGpuTextureFrame {
7435    pub width: u32,
7436    pub height: u32,
7437    pub scale_factor: f64,
7438    /// The texture's index in the descriptor's `textures`.
7439    pub slot: u32,
7440    /// The WGPUTexture.
7441    pub texture: *mut std::ffi::c_void,
7442    /// The WGPUTextureView.
7443    pub texture_view: *mut std::ffi::c_void,
7444    /// The texture's WGPUDevice.
7445    pub device: *mut std::ffi::c_void,
7446    /// The texture's WGPUTextureFormat.
7447    pub format: u32,
7448}
7449impl FromNative<sys::mln_web_gpu_texture_frame> for WebGpuTextureFrame {
7450    unsafe fn from_native(raw: sys::mln_web_gpu_texture_frame) -> Result<Self> {
7451        Ok(Self {
7452            width: raw.width,
7453            height: raw.height,
7454            scale_factor: raw.scale_factor,
7455            slot: raw.slot,
7456            texture: raw.texture,
7457            texture_view: raw.texture_view,
7458            device: raw.device,
7459            format: raw.format,
7460        })
7461    }
7462}
7463
7464/// The WGL objects that a render session makes its OpenGL context from.
7465///
7466/// See `mln_wgl_context_descriptor` in the
7467/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7468#[derive(Debug, Clone, Copy, PartialEq)]
7469pub struct WglContextDescriptor {
7470    /// An `HDC`.
7471    pub device_context: *mut std::ffi::c_void,
7472    /// Your `HGLRC`, for a shared context.
7473    pub share_context: *mut std::ffi::c_void,
7474    /// Your `wglGetProcAddress`, or null to use the system's.
7475    pub get_proc_address: *mut std::ffi::c_void,
7476}
7477impl WglContextDescriptor {
7478    pub fn new(device_context: *mut std::ffi::c_void) -> Self {
7479        Self {
7480            device_context,
7481            share_context: Default::default(),
7482            get_proc_address: Default::default(),
7483        }
7484    }
7485}
7486impl ToNative<sys::mln_wgl_context_descriptor> for WglContextDescriptor {
7487    fn to_native(&self, _arena: &mut InputArena) -> Result<sys::mln_wgl_context_descriptor> {
7488        let mut raw: sys::mln_wgl_context_descriptor = unsafe { std::mem::zeroed() };
7489        raw.device_context = self.device_context;
7490        raw.share_context = self.share_context;
7491        raw.get_proc_address = self.get_proc_address;
7492        Ok(raw)
7493    }
7494}
7495
7496/// A Win32 window to present to, for `MapHandle::attach_win32_window()`.
7497///
7498/// See `mln_win32_window_descriptor` in the
7499/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/win32_8h.html).
7500#[derive(Debug, Clone, Copy, PartialEq)]
7501pub struct Win32WindowDescriptor {
7502    pub logical_size: LogicalSize,
7503    /// Your `HWND`.
7504    pub window: *mut std::ffi::c_void,
7505}
7506impl Win32WindowDescriptor {
7507    pub fn new(logical_size: LogicalSize, window: *mut std::ffi::c_void) -> Self {
7508        Self {
7509            logical_size,
7510            window,
7511        }
7512    }
7513}
7514impl ToNative<sys::mln_win32_window_descriptor> for Win32WindowDescriptor {
7515    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_win32_window_descriptor> {
7516        let mut raw: sys::mln_win32_window_descriptor = unsafe { std::mem::zeroed() };
7517        raw.size = std::mem::size_of::<sys::mln_win32_window_descriptor>() as _;
7518        raw.logical_size = to_native(&self.logical_size, arena)?;
7519        raw.window = self.window;
7520        Ok(raw)
7521    }
7522}
7523
7524/// A new Win32 window for `RenderSessionHandle::set_win32_window_target()`.
7525///
7526/// See `mln_win32_window_replacement` in the
7527/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/win32_8h.html).
7528#[derive(Debug, Clone, Copy, PartialEq)]
7529pub struct Win32WindowReplacement {
7530    pub logical_size: LogicalSize,
7531    /// Your `HWND`.
7532    pub window: *mut std::ffi::c_void,
7533}
7534impl Win32WindowReplacement {
7535    pub fn new(logical_size: LogicalSize, window: *mut std::ffi::c_void) -> Self {
7536        Self {
7537            logical_size,
7538            window,
7539        }
7540    }
7541}
7542impl ToNative<sys::mln_win32_window_replacement> for Win32WindowReplacement {
7543    fn to_native(&self, arena: &mut InputArena) -> Result<sys::mln_win32_window_replacement> {
7544        let mut raw: sys::mln_win32_window_replacement = unsafe { std::mem::zeroed() };
7545        raw.size = std::mem::size_of::<sys::mln_win32_window_replacement>() as _;
7546        raw.logical_size = to_native(&self.logical_size, arena)?;
7547        raw.window = self.window;
7548        Ok(raw)
7549    }
7550}
7551
7552/// The size of a diagnostic message in bytes, with its terminator.
7553///
7554/// See `MLN_DIAGNOSTIC_MESSAGE_CAPACITY` in the
7555/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/base_8h.html).
7556pub const DIAGNOSTIC_MESSAGE_CAPACITY: u32 = sys::MLN_DIAGNOSTIC_MESSAGE_CAPACITY;
7557
7558/// The token of the frame results that a session adds when it renders an image
7559/// for `MapHandle::request_still_image()`. Your own demands can't use it.
7560///
7561/// See `MLN_FRAME_DEMAND_TOKEN_STILL_IMAGE` in the
7562/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__session_8h.html).
7563pub const FRAME_DEMAND_TOKEN_STILL_IMAGE: u64 = sys::MLN_FRAME_DEMAND_TOKEN_STILL_IMAGE;
7564
7565/// The most textures that a render session's texture ring can have.
7566///
7567/// See `MLN_TEXTURE_RING_MAX_DEPTH` in the
7568/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7569pub const TEXTURE_RING_MAX_DEPTH: u32 = sys::MLN_TEXTURE_RING_MAX_DEPTH;
7570
7571/// The null Vulkan non-dispatchable handle.
7572///
7573/// See `MLN_VULKAN_NON_DISPATCHABLE_HANDLE_NULL` in the
7574/// [C API reference](https://maplibre.org/maplibre-native-ffi/reference/c/render__target_8h.html).
7575pub const VULKAN_NON_DISPATCHABLE_HANDLE_NULL: u64 = sys::MLN_VULKAN_NON_DISPATCHABLE_HANDLE_NULL;