maplibre_native/render/
query.rs1use std::ptr;
2
3use maplibre_native_core as maplibre_core;
4use maplibre_native_sys as sys;
5
6use crate::Result;
7use crate::geojson::{Feature, FeatureNativeExt};
8use crate::json::{JsonValue, JsonValueNativeExt};
9
10pub use maplibre_core::query::{
11 FeatureExtensionResult, FeatureStateSelector, QueriedFeature, RenderedFeatureQueryOptions,
12 RenderedQueryGeometry, SourceFeatureQueryOptions,
13};
14pub(crate) use maplibre_core::query::{
15 FeatureStateSelectorNativeExt, NativeRenderedFeatureQueryOptions,
16 NativeSourceFeatureQueryOptions, RenderedFeatureQueryOptionsNativeExt,
17 RenderedQueryGeometryNativeExt, SourceFeatureQueryOptionsNativeExt,
18};
19
20impl super::RenderSessionHandle {
21 pub fn set_feature_state(
23 &self,
24 selector: &FeatureStateSelector,
25 state: &JsonValue,
26 ) -> Result<()> {
27 self.inner.ensure_no_frame_acquired()?;
28 let session = self.inner.as_ptr()?;
29 let selector = selector.to_native();
30 let state = state.try_to_native()?;
31 maplibre_core::check(unsafe {
34 sys::mln_render_session_set_feature_state(session, selector.as_ptr(), state.as_ptr())
35 })
36 }
37
38 pub fn get_feature_state(&self, selector: &FeatureStateSelector) -> Result<JsonValue> {
40 self.inner.ensure_no_frame_acquired()?;
41 let session = self.inner.as_ptr()?;
42 let selector = selector.to_native();
43 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_json_snapshot>::new();
44 maplibre_core::check(unsafe {
47 sys::mln_render_session_get_feature_state(session, selector.as_ptr(), out.as_mut_ptr())
48 })?;
49 Ok(
52 unsafe { maplibre_core::json::copy_json_snapshot(out.into_option()) }?
53 .unwrap_or_else(|| JsonValue::Object(Vec::new())),
54 )
55 }
56
57 pub fn feature_state(&self, selector: &FeatureStateSelector) -> Result<JsonValue> {
59 self.get_feature_state(selector)
60 }
61
62 pub fn remove_feature_state(&self, selector: &FeatureStateSelector) -> Result<()> {
64 self.inner.ensure_no_frame_acquired()?;
65 let session = self.inner.as_ptr()?;
66 let selector = selector.to_native();
67 maplibre_core::check(unsafe {
70 sys::mln_render_session_remove_feature_state(session, selector.as_ptr())
71 })
72 }
73
74 pub fn query_rendered_features(
76 &self,
77 geometry: &RenderedQueryGeometry,
78 options: Option<&RenderedFeatureQueryOptions>,
79 ) -> Result<Vec<QueriedFeature>> {
80 self.inner.ensure_no_frame_acquired()?;
81 let session = self.inner.as_ptr()?;
82 let geometry = geometry.to_native();
83 let options = options
84 .map(RenderedFeatureQueryOptions::to_native)
85 .transpose()?;
86 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_feature_query_result>::new();
87 maplibre_core::check(unsafe {
91 sys::mln_render_session_query_rendered_features(
92 session,
93 geometry.as_ptr(),
94 options
95 .as_ref()
96 .map_or(ptr::null(), NativeRenderedFeatureQueryOptions::as_ptr),
97 out.as_mut_ptr(),
98 )
99 })?;
100 unsafe {
103 maplibre_core::query::copy_feature_query_result(
104 out.into_non_null("mln_feature_query_result")?,
105 )
106 }
107 }
108
109 pub fn query_source_features(
111 &self,
112 source_id: &str,
113 options: Option<&SourceFeatureQueryOptions>,
114 ) -> Result<Vec<QueriedFeature>> {
115 self.inner.ensure_no_frame_acquired()?;
116 let session = self.inner.as_ptr()?;
117 let source_id = maplibre_core::string::string_view(source_id);
118 let options = options
119 .map(SourceFeatureQueryOptions::to_native)
120 .transpose()?;
121 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_feature_query_result>::new();
122 maplibre_core::check(unsafe {
126 sys::mln_render_session_query_source_features(
127 session,
128 source_id.raw(),
129 options
130 .as_ref()
131 .map_or(ptr::null(), NativeSourceFeatureQueryOptions::as_ptr),
132 out.as_mut_ptr(),
133 )
134 })?;
135 unsafe {
138 maplibre_core::query::copy_feature_query_result(
139 out.into_non_null("mln_feature_query_result")?,
140 )
141 }
142 }
143
144 pub fn query_feature_extension(
146 &self,
147 source_id: &str,
148 feature: &Feature,
149 extension: &str,
150 extension_field: &str,
151 arguments: Option<&JsonValue>,
152 ) -> Result<FeatureExtensionResult> {
153 self.inner.ensure_no_frame_acquired()?;
154 let session = self.inner.as_ptr()?;
155 let source_id = maplibre_core::string::string_view(source_id);
156 let extension = maplibre_core::string::string_view(extension);
157 let extension_field = maplibre_core::string::string_view(extension_field);
158 let feature = feature.try_to_native(0)?;
159 if let Some(arguments) = arguments
160 && !matches!(arguments, JsonValue::Object(_))
161 {
162 return Err(crate::Error::invalid_argument(
163 "feature extension arguments must be a JSON object",
164 ));
165 }
166 let arguments = arguments.map(JsonValue::try_to_native).transpose()?;
167 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_feature_extension_result>::new();
168 maplibre_core::check(unsafe {
172 sys::mln_render_session_query_feature_extensions(
173 session,
174 source_id.raw(),
175 feature.as_ptr(),
176 extension.raw(),
177 extension_field.raw(),
178 arguments
179 .as_ref()
180 .map_or(ptr::null(), crate::json::NativeJsonValue::as_ptr),
181 out.as_mut_ptr(),
182 )
183 })?;
184 unsafe {
187 maplibre_core::query::copy_feature_extension_result(
188 out.into_non_null("mln_feature_extension_result")?,
189 )
190 }
191 }
192}