Skip to main content

maplibre_native/
events.rs

1use maplibre_native_core as maplibre_core;
2use maplibre_native_sys as sys;
3
4use crate::Result;
5pub use maplibre_core::events::{
6    OfflineOperationCompletedEvent, OfflineRegionResponseErrorEvent, OfflineRegionStatus,
7    OfflineRegionStatusEvent, OfflineRegionTileCountLimitEvent, RenderFrameEvent, RenderMapEvent,
8    RenderingStats, RuntimeEventPayload, StyleImageMissingEvent, TileActionEvent, TileId,
9    UnknownRuntimeEventPayload,
10};
11pub(crate) use maplibre_core::{OfflineRegionDownloadState, RuntimeEventType};
12
13/// Rust-assigned identity for a map owned by a runtime.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct MapId(u64);
16
17impl MapId {
18    pub(crate) const fn new(value: u64) -> Self {
19        Self(value)
20    }
21
22    /// Returns the runtime-local numeric map identity.
23    pub const fn get(self) -> u64 {
24        self.0
25    }
26}
27
28/// Source object that emitted a runtime event.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30#[non_exhaustive]
31pub enum RuntimeEventSource {
32    Runtime,
33    Map(MapId),
34    UnknownMap,
35    Unknown(u32),
36}
37
38/// Owned runtime event copied from native poll storage.
39#[derive(Debug, Clone, PartialEq)]
40#[non_exhaustive]
41pub struct RuntimeEvent {
42    pub event_type: RuntimeEventType,
43    pub source: RuntimeEventSource,
44    pub code: i32,
45    pub message: Option<String>,
46    pub payload: RuntimeEventPayload,
47}
48
49impl RuntimeEvent {
50    pub(crate) fn from_native(
51        raw: &sys::mln_runtime_event,
52        source: RuntimeEventSource,
53    ) -> Result<Self> {
54        // SAFETY: raw is borrowed from the latest runtime poll result and is
55        // copied before another poll can invalidate event-owned storage.
56        let copied = unsafe { maplibre_core::events::runtime_event_from_native(raw) }?;
57        Ok(Self {
58            event_type: copied.event_type,
59            source,
60            code: copied.code,
61            message: copied.message,
62            payload: copied.payload,
63        })
64    }
65}
66
67pub(crate) fn empty_runtime_event() -> sys::mln_runtime_event {
68    maplibre_core::events::empty_runtime_event()
69}
70
71#[cfg(test)]
72mod tests {
73    use std::mem;
74    use std::ptr;
75
76    use super::*;
77
78    #[test]
79    fn public_runtime_event_applies_rust_source_policy_to_copied_event() {
80        let bytes = [1u8, 2, 3, 4];
81        let message = b"future payload";
82        let source = RuntimeEventSource::Map(MapId::new(42));
83        let raw = sys::mln_runtime_event {
84            size: mem::size_of::<sys::mln_runtime_event>() as u32,
85            type_: 999_001,
86            source_type: sys::MLN_RUNTIME_EVENT_SOURCE_MAP,
87            source: ptr::null_mut(),
88            code: -7,
89            payload_type: 999_002,
90            payload: bytes.as_ptr().cast(),
91            payload_size: bytes.len(),
92            message: message.as_ptr().cast(),
93            message_size: message.len(),
94        };
95
96        let event = RuntimeEvent::from_native(&raw, source).unwrap();
97
98        assert_eq!(event.event_type, RuntimeEventType::Unknown(999_001));
99        assert_eq!(event.source, source);
100        assert_eq!(event.code, -7);
101        assert_eq!(event.message.as_deref(), Some("future payload"));
102        let RuntimeEventPayload::Unknown(payload) = event.payload else {
103            panic!("expected unknown payload");
104        };
105        assert_eq!(payload.raw_type, 999_002);
106        assert_eq!(payload.bytes, bytes.to_vec());
107    }
108}