Skip to main content

maplibre_native_ffi/render/
query.rs

1use std::ptr;
2
3use maplibre_native_ffi_core as maplibre_core;
4use maplibre_native_ffi_sys as sys;
5
6use crate::Result;
7
8pub use maplibre_core::query::{
9    FeatureStateSelector, QueriedFeature, RenderedFeatureQueryOptions, RenderedQueryGeometry,
10    SourceFeatureQueryOptions,
11};
12pub(crate) use maplibre_core::query::{
13    FeatureStateSelectorNativeExt, NativeRenderedFeatureQueryOptions,
14    NativeSourceFeatureQueryOptions, RenderedFeatureQueryOptionsNativeExt,
15    RenderedQueryGeometryNativeExt, SourceFeatureQueryOptionsNativeExt,
16};
17
18impl super::RenderSessionHandle {
19    /// Sets per-feature state on a render source for this session.
20    pub fn set_feature_state(&self, selector: &FeatureStateSelector, state: &[u8]) -> Result<()> {
21        self.inner.ensure_no_frame_acquired()?;
22        let session = self.inner.native()?;
23        let selector = selector.to_native();
24        let state = maplibre_core::string::buffer_view(state);
25        // SAFETY: session is live and all borrowed storage remains valid for the call.
26        maplibre_core::check(unsafe {
27            sys::mln_render_session_set_feature_state(session, selector.as_ptr(), state)
28        })
29    }
30
31    /// Copies per-feature state from a render source in this session.
32    pub fn get_feature_state(&self, selector: &FeatureStateSelector) -> Result<Vec<u8>> {
33        self.inner.ensure_no_frame_acquired()?;
34        let session = self.inner.native()?;
35        let selector = selector.to_native();
36        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
37        // SAFETY: session is live, selector storage remains valid, and out is writable.
38        maplibre_core::check(unsafe {
39            sys::mln_render_session_get_feature_state(session, selector.as_ptr(), out.as_mut_ptr())
40        })?;
41        // SAFETY: Success transfers the owned buffer to this call.
42        unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }
43    }
44
45    /// Removes per-feature state selected for this session.
46    pub fn remove_feature_state(&self, selector: &FeatureStateSelector) -> Result<()> {
47        self.inner.ensure_no_frame_acquired()?;
48        let session = self.inner.native()?;
49        let selector = selector.to_native();
50        // SAFETY: session is live and selector storage remains valid for the call.
51        maplibre_core::check(unsafe {
52            sys::mln_render_session_remove_feature_state(session, selector.as_ptr())
53        })
54    }
55
56    /// Copies rendered features from the latest render session state.
57    pub fn query_rendered_features(
58        &self,
59        geometry: &RenderedQueryGeometry,
60        options: Option<&RenderedFeatureQueryOptions>,
61    ) -> Result<Vec<QueriedFeature>> {
62        self.inner.ensure_no_frame_acquired()?;
63        let session = self.inner.native()?;
64        let geometry = geometry.to_native();
65        let options = options
66            .map(RenderedFeatureQueryOptions::to_native)
67            .transpose()?;
68        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_queried_feature_list>::new();
69        // SAFETY: All descriptors and out storage remain valid for the call.
70        maplibre_core::check(unsafe {
71            sys::mln_render_session_query_rendered_features(
72                session,
73                geometry.as_ptr(),
74                options
75                    .as_ref()
76                    .map_or(ptr::null(), NativeRenderedFeatureQueryOptions::as_ptr),
77                out.as_mut_ptr(),
78            )
79        })?;
80        // SAFETY: On success, the C API returns an owned queried-feature list
81        // handle; core copies and releases it.
82        unsafe {
83            maplibre_core::query::copy_queried_feature_list(
84                out.into_live("mln_queried_feature_list")?,
85            )
86        }
87    }
88
89    /// Copies source features from the latest render session state.
90    pub fn query_source_features(
91        &self,
92        source_id: &str,
93        options: Option<&SourceFeatureQueryOptions>,
94    ) -> Result<Vec<QueriedFeature>> {
95        self.inner.ensure_no_frame_acquired()?;
96        let session = self.inner.native()?;
97        let source_id = maplibre_core::string::string_view(source_id);
98        let options = options
99            .map(SourceFeatureQueryOptions::to_native)
100            .transpose()?;
101        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_queried_feature_list>::new();
102        // SAFETY: All descriptors and out storage remain valid for the call.
103        maplibre_core::check(unsafe {
104            sys::mln_render_session_query_source_features(
105                session,
106                source_id.raw(),
107                options
108                    .as_ref()
109                    .map_or(ptr::null(), NativeSourceFeatureQueryOptions::as_ptr),
110                out.as_mut_ptr(),
111            )
112        })?;
113        // SAFETY: On success, the C API returns an owned queried-feature list
114        // handle; core copies and releases it.
115        unsafe {
116            maplibre_core::query::copy_queried_feature_list(
117                out.into_live("mln_queried_feature_list")?,
118            )
119        }
120    }
121
122    /// Queries a feature extension as UTF-8 JSON or GeoJSON bytes.
123    pub fn query_feature_extension(
124        &self,
125        source_id: &str,
126        feature: &[u8],
127        extension: &str,
128        extension_field: &str,
129        arguments: Option<&[u8]>,
130    ) -> Result<Vec<u8>> {
131        self.inner.ensure_no_frame_acquired()?;
132        let session = self.inner.native()?;
133        let source_id = maplibre_core::string::string_view(source_id);
134        let feature = maplibre_core::string::buffer_view(feature);
135        let extension = maplibre_core::string::string_view(extension);
136        let extension_field = maplibre_core::string::string_view(extension_field);
137        let arguments = arguments.map(maplibre_core::string::buffer_view);
138        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
139        // SAFETY: All views and out storage remain valid for the call.
140        maplibre_core::check(unsafe {
141            sys::mln_render_session_query_feature_extensions(
142                session,
143                source_id.raw(),
144                feature,
145                extension.raw(),
146                extension_field.raw(),
147                arguments.as_ref().map_or(ptr::null(), ptr::from_ref),
148                out.as_mut_ptr(),
149            )
150        })?;
151        // SAFETY: Success transfers the owned buffer to this call.
152        unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }
153    }
154}