Skip to main content

rustial_engine/
lib.rs

1#![warn(missing_docs)]
2#![cfg_attr(not(test), deny(clippy::unwrap_used))]
3// ---------------------------------------------------------------------------
4//! # rustial-engine
5//!
6//! Framework-agnostic 2.5D map engine for the [rustial](https://crates.io/crates/rustial)
7//! geospatial library.
8//!
9//! This crate owns the **core logic** of the map: camera control, layer
10//! management, tile fetching, terrain elevation, vector tessellation,
11//! 3D model placement, and the per-frame update loop that produces a
12//! [`FrameOutput`] consumed by renderers.
13//!
14//! ## Design principles
15//!
16//! | Principle | How it is enforced |
17//! |-----------|--------------------|
18//! | **No GPU code** | Zero dependency on `wgpu`, `bevy`, or any graphics API. Renderers live in separate crates. |
19//! | **No windowing** | No `winit`, no event loop. Input arrives via [`InputEvent`] values pushed by the host. |
20//! | **No async runtime** | Tile I/O uses a synchronous send/poll pattern ([`HttpClient`], [`TileSource`]) so the engine can be embedded anywhere. |
21//! | **Thread-safe** | All public types are `Send + Sync`. [`MapState`] is designed to sit behind an `RwLock`. |
22//! | **Precision** | Coordinates are `f64` (meters, WGS-84). Camera-relative rendering avoids f32 jitter at large Mercator values. |
23//!
24//! ## Module map
25//!
26//! | Module / File | Visibility | Purpose |
27//! |---------------|------------|---------|
28//! | [`camera`] | private | [`Camera`], [`CameraConstraints`], [`CameraController`], [`CameraMode`] |
29//! | [`camera_animator`] | private | [`CameraAnimator`] -- smooth zoom, rotation, and pan momentum |
30//! | [`geometry`] | private | OGC-style geometry model ([`Feature`], [`Geometry`], [`Polygon`], ...) |
31//! | [`input`] | private | [`InputEvent`] enum (Pan, Zoom, Rotate, Resize) |
32//! | [`interaction`] | **public** | Canonical interaction event and target types layered on top of picking |
33//! | [`io`] | **public** | [`HttpClient`], [`HttpRequest`], [`HttpResponse`], [`SharedHttpClient`], [`FetchPool`], [`DiskCache`]* |
34//! | [`layer`] | private | [`Layer`] trait + [`LayerId`] |
35//! | [`layers`] | **public** | [`LayerStack`], [`TileLayer`], [`VectorLayer`], [`ModelLayer`] |
36//! | [`map_state`] | private | [`MapState`], [`FrameOutput`] |
37//! | [`models`] | **public** | [`ModelMesh`], [`ModelInstance`], [`AltitudeMode`] |
38//! | [`simplify`] | private | Douglas-Peucker line simplification |
39//! | [`terrain`] | **public** | [`TerrainManager`], [`TerrainConfig`], elevation sources, mesh building |
40//! | [`tessellator`] | private | Polygon triangulation + thick-line stroking |
41//! | [`tile_cache`] | private | LRU tile cache |
42//! | [`tile_manager`] | private | Tile request scheduling with parent-tile fallback |
43//! | [`tile_request_coordinator`] | private | Cross-source tile request coordination and global budget allocation |
44//! | [`tile_source`] | private | [`TileSource`] trait, [`TileData`], [`TileDecoder`] |
45//! | [`tile_source_http`] | private | [`HttpTileSource`] (URL-template HTTP fetcher) |
46//! | [`geojson`] | **public*** | GeoJSON parser (behind the `geojson` feature flag) |
47//! | [`style`] | **public** | Map style system -- layer configuration, paint, and update logic |
48//! | [`symbols`] | **public** | Symbol and cartography foundation -- sprite atlases, placement, and collision |
49//!
50//! *Items marked with `*` require a Cargo feature flag.
51//!
52//! ## Feature flags
53//!
54//! | Flag | Default | Description |
55//! |------|---------|-------------|
56//! | `geojson` | off | Enables the GeoJSON parser ([`parse_geojson`]) and its `serde`/`serde_json` dependencies. |
57//! | `shapefile` | off | Enables the Shapefile parser ([`parse_shapefile`]) and its `shapefile` dependency. |
58//! | `gltf` | off | Enables [`ModelMesh::from_gltf`] for GLTF/GLB 3D model loading. |
59//! | `obj` | off | Enables [`ModelMesh::from_obj`] for Wavefront OBJ 3D model loading. |
60//! | `disk-cache` | off | Enables [`DiskCache`] for flat-file on-disk tile persistence. |
61//!
62//! ## Re-exported dependency
63//!
64//! This crate depends on [`glam`](https://docs.rs/glam) (workspace version)
65//! for matrix and vector math. The `glam` types appear in public signatures
66//! (e.g. [`FrameOutput::view_projection`] is a `glam::DMat4`). Downstream
67//! crates that interact with these values should use the same `glam` version
68//! declared in the workspace `Cargo.toml`.
69// ---------------------------------------------------------------------------
70
71// ---------------------------------------------------------------------------
72// Modules
73// ---------------------------------------------------------------------------
74
75#[path = "math/bounds.rs"]
76mod bounds;
77#[path = "math/coord.rs"]
78mod coord;
79#[path = "math/elevation.rs"]
80mod elevation;
81#[path = "math/ellipsoid.rs"]
82mod ellipsoid;
83#[path = "math/equirectangular.rs"]
84mod equirectangular;
85#[path = "math/frustum.rs"]
86mod frustum;
87#[path = "math/geodesic.rs"]
88mod geodesic;
89#[path = "math/globe.rs"]
90mod globe;
91#[path = "math/mercator.rs"]
92mod mercator;
93#[path = "math/projection.rs"]
94mod projection;
95#[path = "math/tile.rs"]
96mod tile;
97#[path = "math/vertical_perspective.rs"]
98mod vertical_perspective;
99
100pub mod async_data;
101mod camera;
102mod camera_animator;
103mod camera_projection;
104pub mod cluster;
105pub mod event_emitter;
106pub mod expression;
107pub(crate) mod geo_wrap;
108#[cfg(feature = "geojson")]
109pub mod geojson;
110mod geometry;
111pub mod geometry_ops;
112pub mod gesture;
113pub mod image_compare;
114mod input;
115pub mod interaction;
116pub mod interaction_manager;
117pub mod io;
118mod layer;
119pub mod layers;
120pub mod loading_placeholder;
121mod map_state;
122pub mod models;
123pub mod mvt;
124pub mod picking;
125mod pooled_tile_source;
126pub mod query;
127pub mod regression;
128#[cfg(feature = "shapefile")]
129pub mod shapefile_parser;
130pub mod shapes;
131mod simplify;
132mod streamed_payload;
133pub mod style;
134#[cfg(feature = "style-json")]
135pub mod style_json;
136pub mod symbols;
137pub mod terrain;
138mod tessellator;
139mod tile_cache;
140mod tile_lifecycle;
141mod tile_manager;
142mod tile_request_coordinator;
143mod tile_source;
144mod tile_source_http;
145mod tile_source_vector_http;
146pub mod tilejson;
147pub mod visualization;
148
149pub mod precision_invariants;
150
151#[cfg(test)]
152mod support_contract;
153#[cfg(test)]
154mod visualization_contract;
155
156pub extern crate self as rustial_math;
157
158// ---------------------------------------------------------------------------
159// Re-exports -- Math primitives
160// ---------------------------------------------------------------------------
161
162pub use bounds::{GeoBounds, WorldBounds};
163pub use coord::{GeoCoord, WorldCoord};
164pub use elevation::ElevationGrid;
165pub use ellipsoid::Ellipsoid;
166pub use equirectangular::Equirectangular;
167pub use frustum::{
168    Frustum, Plane, PLANE_BOTTOM, PLANE_FAR, PLANE_LEFT, PLANE_NEAR, PLANE_RIGHT, PLANE_TOP,
169};
170pub use geodesic::{
171    geodesic_destination, geodesic_destination_on, geodesic_distance, geodesic_distance_on,
172    GeodesicResult, VincentyConvergenceError,
173};
174pub use globe::Globe;
175pub use mercator::WebMercator;
176pub use projection::Projection;
177pub use tile::{
178    geo_to_tile, geo_to_tile_checked, tile_bounds_world, tile_to_geo, tile_xy_to_geo,
179    visible_tiles, visible_tiles_checked, visible_tiles_covering, visible_tiles_flat_view,
180    visible_tiles_flat_view_capped, visible_tiles_flat_view_capped_with_config,
181    visible_tiles_flat_view_refined_capped, visible_tiles_flat_view_refined_capped_with_config,
182    visible_tiles_flat_view_with_config, visible_tiles_frustum, visible_tiles_lod, CoveringCamera,
183    CoveringTilesOptions, FlatTileSelectionConfig, FlatTileView, TileCoord, TileId, MAX_ZOOM,
184};
185pub use vertical_perspective::VerticalPerspective;
186
187// ---------------------------------------------------------------------------
188// Re-exports -- Camera & Input
189// ---------------------------------------------------------------------------
190
191pub use camera::{Camera, CameraConstraints, CameraController, CameraMode};
192pub use camera_animator::{CameraAnimator, EaseToOptions, FlyToOptions};
193pub use camera_projection::CameraProjection;
194pub use input::{InputEvent, TouchContact, TouchPhase};
195pub use interaction::{
196    InteractionButton, InteractionEvent, InteractionEventKind, InteractionModifiers,
197    InteractionTarget, InteractionTargetKind, PointerKind, ScreenPoint,
198};
199pub use interaction_manager::{InteractionConfig, InteractionManager};
200
201// ---------------------------------------------------------------------------
202// Re-exports -- Layer system
203// ---------------------------------------------------------------------------
204
205pub use expression::{
206    BoolExpression, ExprEvalContext, Expression, NumericExpression, StringExpression,
207};
208pub use layer::{Layer, LayerId, LayerKind};
209pub use layers::{
210    BackgroundLayer, CallbackFrameProvider, CircleInstanceData, DynamicImageOverlayLayer,
211    FrameData, FrameProvider, FrameProviderFactory, HillshadeLayer, HillshadeParams,
212    ImageOverlayData, ImageOverlayLayer, LayerStack, ModelLayer, PatternImage, TileLayer,
213    VectorLayer, VectorMeshData, VectorRenderMode, VectorStyle,
214};
215pub use style::{
216    atmospheric_clear_color,
217    // Feature-state-driven style resolution helpers.
218    circle_style_with_state,
219    compute_fog,
220    compute_lighting,
221    compute_shadow_cascades,
222    compute_sky,
223    fill_extrusion_style_with_state,
224    fill_style_with_state,
225    heatmap_style_with_state,
226    line_style_with_state,
227    symbol_style_with_state,
228    vector_style_with_state,
229    AmbientLight,
230    BackgroundStyleLayer,
231    CanvasSource,
232    CircleStyleLayer,
233    ComputedFog,
234    ComputedLighting,
235    ComputedShadow,
236    ComputedSky,
237    DirectionalLight,
238    FillExtrusionStyleLayer,
239    FillStyleLayer,
240    // Fog / atmosphere configuration.
241    FogConfig,
242    FromFeatureStateProperty,
243    GeoJsonSource,
244    HeatmapStyleLayer,
245    HillshadeStyleLayer,
246    ImageSource,
247    LayerTransitionState,
248    // Lighting configuration.
249    LightConfig,
250    LightingMode,
251    LineStyleLayer,
252    MapStyle,
253    ModelSource,
254    ModelStyleLayer,
255    RasterSource,
256    RasterStyleLayer,
257    ResolvedTransitions,
258    // Shadow map configuration.
259    ShadowConfig,
260    // Sky / atmosphere configuration.
261    SkyConfig,
262    SkyType,
263    StyleDocument,
264    StyleError,
265    StyleEvalContext,
266    StyleEvalContextFull,
267    StyleLayer,
268    StyleLayerId,
269    StyleLayerMeta,
270    StyleProjection,
271    StyleSource,
272    StyleSourceId,
273    StyleSourceKind,
274    StyleValue,
275    SymbolStyleLayer,
276    TerrainSource,
277    // Style transition types.
278    TransitionSpec,
279    Transitioning,
280    VectorStyleLayer,
281    VectorTileSource,
282    VideoSource,
283};
284#[cfg(feature = "style-json")]
285pub use style_json::{
286    parse_style_json, StyleSourceRegistry, StyleSpecDocument, StyleSpecError, StyleSpecLayer,
287    StyleSpecLayerType, StyleSpecProjection, StyleSpecProjectionType, StyleSpecSource,
288    StyleSpecSourceType, StyleSpecTerrain, StyleSpecTransition,
289};
290
291// ---------------------------------------------------------------------------
292// Re-exports -- Map state & frame output
293// ---------------------------------------------------------------------------
294
295pub use event_emitter::{EventEmitter, ListenerId};
296pub use loading_placeholder::{LoadingPlaceholder, PlaceholderGenerator, PlaceholderStyle};
297pub use map_state::{
298    FitBoundsOptions, FitBoundsPadding, FrameOutput, MapState, TilePipelineDiagnostics,
299};
300pub use regression::{
301    TilePipelineRegressionEvaluation, TilePipelineRegressionParseError,
302    TilePipelineRegressionSample, TilePipelineRegressionSummary, TilePipelineRegressionThresholds,
303    TilePipelineRegressionViolation, TILE_PIPELINE_REGRESSION_CSV_HEADER,
304};
305
306// ---------------------------------------------------------------------------
307// Re-exports -- Geometry & vector data
308// ---------------------------------------------------------------------------
309
310pub use geometry::{
311    Feature, FeatureCollection, Geometry, LineString, MultiLineString, MultiPoint, MultiPolygon,
312    Point, Polygon, PropertyValue,
313};
314
315pub use cluster::{ClusterOptions, PointCluster};
316pub use gesture::GestureRecognizer;
317
318#[cfg(feature = "geojson")]
319pub use geojson::{parse_geojson, GeoJsonError};
320
321#[cfg(feature = "shapefile")]
322pub use shapefile_parser::{parse_shapefile, ShapefileError};
323
324pub use geometry_ops::{
325    bearing, geometry_bbox, geometry_centroid, initial_bearing, interpolate_great_circle,
326    linestring_length, polygon_area, ring_area,
327};
328pub use simplify::{simplify_douglas_peucker, simplify_polygon_ring};
329pub use tessellator::{
330    stroke_line, stroke_line_styled, triangulate_polygon, triangulate_polygon_with_holes,
331    StrokeLineResult,
332};
333
334// ---------------------------------------------------------------------------
335// Re-exports -- Tile engine
336// ---------------------------------------------------------------------------
337
338pub use pooled_tile_source::{
339    PooledRasterTileSourceConfig, PooledTileSource, DEFAULT_RASTER_TILE_URL,
340    DEFAULT_RASTER_TILE_USER_AGENT,
341};
342pub use tile_cache::{TileCache, TileCacheEntry, TileCacheStats};
343pub use tile_lifecycle::{
344    TileLifecycleDiagnostics, TileLifecycleEvent, TileLifecycleEventKind, TileLifecycleRecord,
345};
346pub use tile_manager::{
347    TileManager, TileManagerCounters, TilePixelRect, TileSelectionConfig, TileSelectionStats,
348    TileTextureRegion, VisibleTile, VisibleTileSet,
349};
350pub use tile_request_coordinator::{
351    CoordinatorConfig, CoordinatorStats, SourcePriority, TileRequestCoordinator,
352};
353pub use tile_source::{
354    DecodedImage, RasterMipChain, RasterMipLevel, RawVectorPayload, RevalidationHint, TileData,
355    TileDecoder, TileError, TileFreshness, TileResponse, TileSource, TileSourceDiagnostics,
356    TileSourceFailureDiagnostics, VectorTileData,
357};
358pub use tile_source_http::HttpTileSource;
359pub use tile_source_vector_http::HttpVectorTileSource;
360
361// ---------------------------------------------------------------------------
362// Re-exports -- I/O
363// ---------------------------------------------------------------------------
364
365pub use io::{FetchPool, HttpClient, HttpRequest, HttpResponse, SharedHttpClient};
366
367#[cfg(all(feature = "disk-cache", not(target_arch = "wasm32")))]
368pub use io::{DiskCache, DiskCacheError};
369
370// ---------------------------------------------------------------------------
371// Re-exports -- Terrain & elevation
372// ---------------------------------------------------------------------------
373
374pub use terrain::{
375    build_terrain_descriptor, build_terrain_descriptor_with_source, build_terrain_mesh,
376    build_terrain_mesh_with_source, elevation_region_in_texture_space, expand_with_clamped_border,
377    interior_dims, materialize_terrain_mesh, patch_border_edge, patch_changed_tiles,
378    prepare_hillshade_raster, skirt_height, BackfillState, ElevationSource,
379    ElevationSourceDiagnostics, ElevationSourceFailureDiagnostics, FlatElevationSource,
380    HttpElevationSource, PreparedHillshadeRaster, QuantizedMeshSource, TerrainConfig,
381    TerrainDiagnostics, TerrainElevationTexture, TerrainError, TerrainManager, TerrainMeshData,
382    TerrainRgbEncoding, NEIGHBOR_OFFSETS,
383};
384
385// ---------------------------------------------------------------------------
386// Re-exports -- 3D models
387// ---------------------------------------------------------------------------
388
389pub use models::{AltitudeMode, ModelInstance, ModelLoadError, ModelMesh};
390
391// ---------------------------------------------------------------------------
392// Re-exports -- Symbols and cartography foundation
393// ---------------------------------------------------------------------------
394
395pub use symbols::{
396    cross_tile_index::{CrossTileSymbolIndex, SymbolCandidateEntry},
397    layout_symbol_glyphs, GlyphAtlas, GlyphAtlasEntry, GlyphKey, GlyphProvider, GlyphQuad,
398    GlyphRaster, ImageManager, PlacedSymbol, ProceduralGlyphProvider, SpriteImage, SpriteSheet,
399    SymbolAnchor, SymbolAssetDependencies, SymbolAssetRegistry, SymbolCandidate,
400    SymbolCollisionBox, SymbolIconTextFit, SymbolPlacement, SymbolPlacementConfig,
401    SymbolPlacementEngine, SymbolTextJustify, SymbolTextTransform, SymbolWritingMode,
402};
403
404// ---------------------------------------------------------------------------
405// Re-exports -- Query API
406// ---------------------------------------------------------------------------
407
408pub use query::{
409    geometry_intersects_bbox, FeatureState, FeatureStateId, GeoBBox, QueriedFeature, QueryOptions,
410};
411
412// ---------------------------------------------------------------------------
413// Re-exports -- Picking API
414// ---------------------------------------------------------------------------
415
416pub use picking::{
417    HitCategory, HitProvenance, NonPickableLayerKind, PickHit, PickOptions, PickQuery, PickResult,
418    PickableLayerKind,
419};
420
421// ---------------------------------------------------------------------------
422// Re-exports -- Visualization primitives
423// ---------------------------------------------------------------------------
424
425pub use visualization::{
426    ColorRamp, ColorStop, ColumnInstance, ColumnInstanceSet, ExtrusionParams, GeoGrid,
427    GridExtrusionLayer, GridScalarLayer, InstancedColumnLayer, LabeledStop, LegendSpec,
428    NormalizationMode, PointCloudLayer, PointInstance, PointInstanceSet, ScalarField2D,
429    VisualizationOverlay,
430};
431
432// ---------------------------------------------------------------------------
433// Re-exports -- Image comparison (cross-renderer parity)
434// ---------------------------------------------------------------------------
435
436pub use image_compare::{compute_rmse, count_differing_pixels, differing_pixel_fraction};
437
438// ---------------------------------------------------------------------------
439// Re-exports -- TileJSON metadata
440// ---------------------------------------------------------------------------
441
442#[cfg(feature = "style-json")]
443pub use tilejson::{parse_tilejson, parse_tilejson_value};
444pub use tilejson::{TileJson, TileJsonError, TileScheme, VectorLayerMeta};
445
446// ---------------------------------------------------------------------------
447// Re-exports -- MVT decoder
448// ---------------------------------------------------------------------------
449
450pub use mvt::{decode_mvt, DecodedVectorTile, MvtDecodeOptions, MvtError};
451
452// ---------------------------------------------------------------------------
453// Re-exports -- Async data pipeline
454// ---------------------------------------------------------------------------
455
456pub use async_data::{
457    partition_features_by_tile, AsyncVisualizationPipeline, DataTaskPool, DataTaskResultReceiver,
458    MvtDecodeOutput, TerrainCacheKey, TerrainTaskInput, TerrainTaskOutput, ThreadDataTaskPool,
459    VectorBucketKey, VectorCacheKey, VectorTaskInput, VectorTaskOutput, VisualizationTaskOutput,
460};
461
462// ---------------------------------------------------------------------------
463// Compile-time Send + Sync assertions
464//
465// Every public data type that downstream code may share across threads
466// must be Send + Sync.  These zero-cost assertions catch regressions at
467// compile time rather than in production.
468// ---------------------------------------------------------------------------
469
470#[allow(dead_code)]
471const _: () = {
472    fn assert_send_sync<T: Send + Sync>() {}
473    fn assertions() {
474        // Math primitives
475        assert_send_sync::<GeoCoord>();
476        assert_send_sync::<WorldCoord>();
477        assert_send_sync::<GeoBounds>();
478        assert_send_sync::<WorldBounds>();
479        assert_send_sync::<Ellipsoid>();
480        assert_send_sync::<Frustum>();
481        assert_send_sync::<Plane>();
482        assert_send_sync::<TileId>();
483        assert_send_sync::<TileCoord>();
484        assert_send_sync::<FlatTileSelectionConfig>();
485        assert_send_sync::<FlatTileView>();
486        assert_send_sync::<CoveringCamera>();
487        assert_send_sync::<CoveringTilesOptions>();
488        assert_send_sync::<GeodesicResult>();
489        assert_send_sync::<ElevationGrid>();
490        assert_send_sync::<VincentyConvergenceError>();
491        assert_send_sync::<WebMercator>();
492        assert_send_sync::<Equirectangular>();
493        assert_send_sync::<Globe>();
494        assert_send_sync::<VerticalPerspective>();
495
496        // Camera & input
497        assert_send_sync::<Camera>();
498        assert_send_sync::<CameraConstraints>();
499        assert_send_sync::<CameraMode>();
500        assert_send_sync::<CameraProjection>();
501        assert_send_sync::<CameraAnimator>();
502        assert_send_sync::<InputEvent>();
503
504        // Layer system
505        assert_send_sync::<BackgroundLayer>();
506        assert_send_sync::<HillshadeLayer>();
507        assert_send_sync::<LayerId>();
508        assert_send_sync::<LayerStack>();
509        assert_send_sync::<TileLayer>();
510        assert_send_sync::<VectorLayer>();
511        assert_send_sync::<ModelLayer>();
512        assert_send_sync::<VectorStyle>();
513        assert_send_sync::<VectorMeshData>();
514        assert_send_sync::<StyleDocument>();
515        assert_send_sync::<MapStyle>();
516
517        // Map state
518        assert_send_sync::<MapState>();
519        assert_send_sync::<FrameOutput>();
520        assert_send_sync::<FeatureState>();
521        assert_send_sync::<FeatureStateId>();
522        assert_send_sync::<QueriedFeature>();
523        assert_send_sync::<QueryOptions>();
524
525        // Picking
526        assert_send_sync::<PickQuery>();
527        assert_send_sync::<PickOptions>();
528        assert_send_sync::<PickHit>();
529        assert_send_sync::<PickResult>();
530
531        // Geometry
532        assert_send_sync::<Feature>();
533        assert_send_sync::<FeatureCollection>();
534        assert_send_sync::<Geometry>();
535        assert_send_sync::<PropertyValue>();
536
537        // Tile engine
538        assert_send_sync::<TileCache>();
539        assert_send_sync::<TileCacheEntry>();
540        assert_send_sync::<TileCacheStats>();
541        assert_send_sync::<TileManager>();
542        assert_send_sync::<TileManagerCounters>();
543        assert_send_sync::<TilePixelRect>();
544        assert_send_sync::<TileSelectionConfig>();
545        assert_send_sync::<TileSelectionStats>();
546        assert_send_sync::<TilePipelineDiagnostics>();
547        assert_send_sync::<TileTextureRegion>();
548        assert_send_sync::<VisibleTile>();
549        assert_send_sync::<VisibleTileSet>();
550        assert_send_sync::<DecodedImage>();
551        assert_send_sync::<RasterMipChain>();
552        assert_send_sync::<RasterMipLevel>();
553        assert_send_sync::<TileData>();
554        assert_send_sync::<TileError>();
555        assert_send_sync::<TileSourceDiagnostics>();
556        assert_send_sync::<PooledTileSource>();
557        assert_send_sync::<VectorTileData>();
558
559        // TileJSON
560        assert_send_sync::<TileJson>();
561        assert_send_sync::<TileJsonError>();
562        assert_send_sync::<TileScheme>();
563        assert_send_sync::<VectorLayerMeta>();
564
565        // MVT
566        assert_send_sync::<MvtDecodeOptions>();
567        assert_send_sync::<MvtError>();
568
569        // I/O
570        assert_send_sync::<FetchPool>();
571        assert_send_sync::<HttpRequest>();
572        assert_send_sync::<HttpResponse>();
573
574        // Terrain
575        assert_send_sync::<TerrainConfig>();
576        assert_send_sync::<TerrainError>();
577        assert_send_sync::<TerrainManager>();
578        assert_send_sync::<TerrainMeshData>();
579        assert_send_sync::<PreparedHillshadeRaster>();
580        assert_send_sync::<TerrainRgbEncoding>();
581        assert_send_sync::<TerrainSource>();
582        assert_send_sync::<VectorTileSource>();
583        assert_send_sync::<ImageSource>();
584        assert_send_sync::<VideoSource>();
585        assert_send_sync::<CanvasSource>();
586        assert_send_sync::<GlyphAtlas>();
587        assert_send_sync::<GlyphAtlasEntry>();
588        assert_send_sync::<GlyphKey>();
589        assert_send_sync::<GlyphRaster>();
590        assert_send_sync::<ImageManager>();
591        assert_send_sync::<PlacedSymbol>();
592        assert_send_sync::<ProceduralGlyphProvider>();
593        assert_send_sync::<SpriteImage>();
594        assert_send_sync::<SpriteSheet>();
595        assert_send_sync::<SymbolAnchor>();
596        assert_send_sync::<SymbolAssetDependencies>();
597        assert_send_sync::<SymbolAssetRegistry>();
598        assert_send_sync::<SymbolCandidate>();
599        assert_send_sync::<SymbolCollisionBox>();
600        assert_send_sync::<SymbolPlacementConfig>();
601        assert_send_sync::<SymbolPlacementEngine>();
602        assert_send_sync::<SymbolWritingMode>();
603
604        // Models
605        assert_send_sync::<ModelInstance>();
606        assert_send_sync::<ModelMesh>();
607        assert_send_sync::<AltitudeMode>();
608        assert_send_sync::<GeoJsonSource>();
609        assert_send_sync::<ModelSource>();
610
611        // Visualization
612        assert_send_sync::<GeoGrid>();
613        assert_send_sync::<ScalarField2D>();
614        assert_send_sync::<ColorRamp>();
615        assert_send_sync::<ColorStop>();
616        assert_send_sync::<LegendSpec>();
617        assert_send_sync::<ColumnInstance>();
618        assert_send_sync::<ColumnInstanceSet>();
619        assert_send_sync::<PointInstance>();
620        assert_send_sync::<PointInstanceSet>();
621        assert_send_sync::<GridScalarLayer>();
622        assert_send_sync::<GridExtrusionLayer>();
623        assert_send_sync::<InstancedColumnLayer>();
624        assert_send_sync::<PointCloudLayer>();
625        assert_send_sync::<VisualizationOverlay>();
626    }
627};