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    NativeRenderedFeatureQueryOptions, NativeSourceFeatureQueryOptions,
14    RenderedFeatureQueryOptionsNativeExt, RenderedQueryGeometryNativeExt,
15    SourceFeatureQueryOptionsNativeExt,
16};
17
18impl super::RenderSessionHandle {
19    /// Copies rendered features from the latest render session state.
20    pub fn query_rendered_features(
21        &self,
22        geometry: &RenderedQueryGeometry,
23        options: Option<&RenderedFeatureQueryOptions>,
24    ) -> Result<Vec<QueriedFeature>> {
25        self.inner.ensure_no_frame_acquired()?;
26        let session = self.inner.native()?;
27        let geometry = geometry.to_native();
28        let options = options
29            .map(RenderedFeatureQueryOptions::to_native)
30            .transpose()?;
31        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_queried_feature_list>::new();
32        // SAFETY: All descriptors and out storage remain valid for the call.
33        maplibre_core::check(unsafe {
34            sys::mln_render_session_query_rendered_features(
35                session,
36                geometry.as_ptr(),
37                options
38                    .as_ref()
39                    .map_or(ptr::null(), NativeRenderedFeatureQueryOptions::as_ptr),
40                out.as_mut_ptr(),
41            )
42        })?;
43        // SAFETY: On success, the C API returns an owned queried-feature list
44        // handle; core copies and releases it.
45        unsafe {
46            maplibre_core::query::copy_queried_feature_list(
47                out.into_live("mln_queried_feature_list")?,
48            )
49        }
50    }
51
52    /// Copies source features from the latest render session state.
53    pub fn query_source_features(
54        &self,
55        source_id: &str,
56        options: Option<&SourceFeatureQueryOptions>,
57    ) -> Result<Vec<QueriedFeature>> {
58        self.inner.ensure_no_frame_acquired()?;
59        let session = self.inner.native()?;
60        let source_id = maplibre_core::string::string_view(source_id);
61        let options = options
62            .map(SourceFeatureQueryOptions::to_native)
63            .transpose()?;
64        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_queried_feature_list>::new();
65        // SAFETY: All descriptors and out storage remain valid for the call.
66        maplibre_core::check(unsafe {
67            sys::mln_render_session_query_source_features(
68                session,
69                source_id.raw(),
70                options
71                    .as_ref()
72                    .map_or(ptr::null(), NativeSourceFeatureQueryOptions::as_ptr),
73                out.as_mut_ptr(),
74            )
75        })?;
76        // SAFETY: On success, the C API returns an owned queried-feature list
77        // handle; core copies and releases it.
78        unsafe {
79            maplibre_core::query::copy_queried_feature_list(
80                out.into_live("mln_queried_feature_list")?,
81            )
82        }
83    }
84
85    /// Queries a feature extension as UTF-8 JSON or GeoJSON bytes.
86    pub fn query_feature_extension(
87        &self,
88        source_id: &str,
89        feature: &[u8],
90        extension: &str,
91        extension_field: &str,
92        arguments: Option<&[u8]>,
93    ) -> Result<Vec<u8>> {
94        self.inner.ensure_no_frame_acquired()?;
95        let session = self.inner.native()?;
96        let source_id = maplibre_core::string::string_view(source_id);
97        let feature = maplibre_core::string::buffer_view(feature);
98        let extension = maplibre_core::string::string_view(extension);
99        let extension_field = maplibre_core::string::string_view(extension_field);
100        let arguments = arguments.map(maplibre_core::string::buffer_view);
101        let mut out = maplibre_core::ptr::OutHandle::<sys::mln_buffer>::new();
102        // SAFETY: All views and out storage remain valid for the call.
103        maplibre_core::check(unsafe {
104            sys::mln_render_session_query_feature_extensions(
105                session,
106                source_id.raw(),
107                feature,
108                extension.raw(),
109                extension_field.raw(),
110                arguments.as_ref().map_or(ptr::null(), ptr::from_ref),
111                out.as_mut_ptr(),
112            )
113        })?;
114        // SAFETY: Success transfers the owned buffer to this call.
115        unsafe { maplibre_core::string::copy_owned_buffer(out.get()) }
116    }
117}