Skip to main content

mlt_core/encoder/
model.rs

1use derive_debug::Dbg;
2
3use crate::decoder::{DictionaryType, GeometryValues, StreamType};
4use crate::encoder::geometry::VertexBufferType;
5use crate::encoder::{IntEncoder, StagedId, StagedProperty};
6
7/// Owned variant of `Unknown`.
8#[derive(Debug, Clone, Default, PartialEq)]
9pub struct EncodedUnknown {
10    pub(crate) tag: u8,
11    pub(crate) value: Vec<u8>,
12}
13
14/// Parameters derived from the vertex set of a feature collection, used to
15/// normalize coordinates before space-filling-curve key computation.
16#[derive(Debug, Clone, Copy, PartialEq)]
17pub struct CurveParams {
18    pub shift: u32,
19    pub bits: u32,
20}
21
22impl Default for CurveParams {
23    fn default() -> Self {
24        Self { shift: 0, bits: 1 }
25    }
26}
27
28impl CurveParams {
29    /// Compute params from a flat `[x0, y0, x1, y1, …]` vertex slice.
30    #[must_use]
31    pub fn from_vertices(vertices: &[i32]) -> Self {
32        if vertices.is_empty() {
33            return Self::default();
34        }
35        let (min, max) = vertices
36            .iter()
37            .fold((i32::MAX, i32::MIN), |(mn, mx), &v| (mn.min(v), mx.max(v)));
38        crate::codecs::hilbert::hilbert_curve_params_from_bounds(min, max)
39    }
40}
41
42/// Columnar layer data being prepared for encoding (stage 2 of the encoding pipeline).
43///
44/// Holds fully-owned columnar data. Constructed directly (synthetics, benches) or
45/// converted from [`TileLayer`](crate::TileLayer).
46/// Consumed by encoding via [`StagedLayer::encode_into`] or `StagedLayer::encode_explicit`
47/// (with explicit encoding mode enabled).
48#[derive(Debug, PartialEq, Clone)]
49pub struct StagedLayer {
50    pub name: String,
51    pub extent: u32,
52    pub id: StagedId,
53    pub geometry: GeometryValues,
54    pub properties: Vec<StagedProperty>,
55}
56
57/// Global encoder settings controlling which optimization strategies are attempted.
58#[derive(Debug, Clone, Copy, PartialEq, Hash)]
59#[expect(
60    clippy::struct_excessive_bools,
61    reason = "enums would not model this better, not a state machine"
62)]
63pub struct EncoderConfig {
64    /// Generate tessellation data for polygons and multi-polygons.
65    pub tessellate: bool,
66    /// Try sorting features by the Z-order (Morton) curve index of their first vertex.
67    pub try_spatial_morton_sort: bool,
68    /// Try sorting features by the Hilbert curve index of their first vertex.
69    pub try_spatial_hilbert_sort: bool,
70    /// Try sorting features by their feature ID in ascending order.
71    pub try_id_sort: bool,
72    /// Allow `FSST` string compression
73    pub allow_fsst: bool,
74    /// Allow `FastPFOR` integer compression
75    pub allow_fpf: bool,
76    /// Allow string grouping into shared dictionaries
77    pub allow_shared_dict: bool,
78}
79impl Default for EncoderConfig {
80    fn default() -> Self {
81        Self {
82            tessellate: false,
83            try_spatial_morton_sort: true,
84            try_spatial_hilbert_sort: true,
85            try_id_sort: true,
86            allow_fsst: true,
87            allow_fpf: true,
88            allow_shared_dict: true,
89        }
90    }
91}
92
93/// How to encode a string column.
94///
95/// Used by [`ExplicitEncoder`] to control per-column string encoding in the
96/// explicit (synthetics / `__private`) path and in property-encoding helpers.
97///
98/// Publicly visible only when the `__private` feature is enabled (re-exported from
99/// [`crate::encoder`]).  Always compiled so that the unified property-encoding path
100/// can reference it without feature flags.
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub enum StrEncoding {
103    Plain,
104    Dict,
105    Fsst,
106    FsstDict,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq)]
110pub enum ColumnKind {
111    Id,
112    Geometry,
113    Property,
114}
115
116/// Context for per-stream encoding decisions in [`ExplicitEncoder`] callbacks.
117#[derive(Clone, Copy, Debug, PartialEq)]
118pub struct StreamCtx<'a> {
119    pub kind: ColumnKind,
120    pub stream_type: StreamType,
121    pub name: &'a str,
122    pub subname: &'a str,
123}
124impl<'a> StreamCtx<'a> {
125    /// Stream with a logical sub-part (e.g. string column `"lengths"` / `"offsets"`, shared-dict child suffix).
126    #[inline]
127    #[must_use]
128    pub const fn new(
129        kind: ColumnKind,
130        stream_type: StreamType,
131        name: &'a str,
132        subname: &'a str,
133    ) -> Self {
134        Self {
135            kind,
136            stream_type,
137            name,
138            subname,
139        }
140    }
141
142    #[inline]
143    #[must_use]
144    pub const fn id(stream_type: StreamType) -> Self {
145        Self::new(ColumnKind::Id, stream_type, "", "")
146    }
147
148    #[inline]
149    #[must_use]
150    pub const fn geom(stream_type: StreamType, name: &'a str) -> Self {
151        Self::new(ColumnKind::Geometry, stream_type, name, "")
152    }
153
154    #[inline]
155    #[must_use]
156    pub const fn prop(stream_type: StreamType, name: &'a str) -> Self {
157        Self::new(ColumnKind::Property, stream_type, name, "")
158    }
159
160    #[inline]
161    #[must_use]
162    pub const fn prop_data(name: &'a str) -> Self {
163        let stream_type = StreamType::Data(DictionaryType::None);
164        Self::new(ColumnKind::Property, stream_type, name, "")
165    }
166
167    #[inline]
168    #[must_use]
169    pub const fn prop2(stream_type: StreamType, prefix: &'a str, suffix: &'a str) -> Self {
170        Self::new(ColumnKind::Property, stream_type, prefix, suffix)
171    }
172}
173
174/// Explicit, deterministic encoding configuration for synthetics and tests.
175///
176/// All encoding choices are caller-specified via callbacks so one struct can cover
177/// any combination without per-stream boilerplate.
178///
179/// Always compiled; publicly visible only when the `__private` feature is enabled
180/// (re-exported from [`crate::encoder`]).
181#[derive(Dbg)]
182pub struct ExplicitEncoder {
183    /// Vertex buffer layout for geometry streams.
184    pub vertex_buffer_type: VertexBufferType,
185    /// Per-stream override for the skip-empty-stream rule used by `write_geo_u32_stream`.
186    #[dbg(skip)]
187    pub force_stream: Box<dyn for<'a> Fn(&'a StreamCtx<'a>) -> bool>,
188    /// Return the [`IntEncoder`] for a stream identified by [`StreamCtx`].
189    #[dbg(skip)]
190    pub get_int_encoder: Box<dyn for<'a> Fn(&'a StreamCtx<'a>) -> IntEncoder>,
191    /// Return the string encoding strategy for a string property column.
192    #[dbg(skip)]
193    pub get_str_encoding: Box<dyn Fn(&str) -> StrEncoding>,
194}