mlt_core/convert/
infer.rs1use std::collections::HashMap;
5
6use crate::tile::PropKind;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum InferredKind {
12 Unknown,
13 Bool,
14 I64,
15 U64,
16 F32,
17 F64,
18 Str,
19}
20
21impl InferredKind {
22 #[must_use]
26 pub fn merge(self, other: Self) -> Self {
27 if self == Self::Unknown {
28 return other;
29 }
30 if other == Self::Unknown || self == other {
31 return self;
32 }
33 #[expect(clippy::match_same_arms)]
34 match (self, other) {
35 (Self::I64 | Self::U64, Self::I64 | Self::U64) => Self::I64,
37 (Self::F32 | Self::F64, Self::F32 | Self::F64) => Self::F64,
39 (Self::I64 | Self::U64, Self::F32 | Self::F64)
42 | (Self::F32 | Self::F64, Self::I64 | Self::U64) => Self::F64,
43 _ => Self::Str,
44 }
45 }
46
47 #[must_use]
48 pub fn prop_kind(self) -> PropKind {
49 match self {
50 Self::Unknown | Self::Str => PropKind::Str,
51 Self::Bool => PropKind::Bool,
52 Self::I64 => PropKind::I64,
53 Self::U64 => PropKind::U64,
54 Self::F32 => PropKind::F32,
55 Self::F64 => PropKind::F64,
56 }
57 }
58}
59
60#[derive(Default)]
62pub(crate) struct ColumnInference<'a> {
63 index: HashMap<&'a str, usize>,
64 names: Vec<String>,
65 kinds: Vec<InferredKind>,
66}
67
68impl<'a> ColumnInference<'a> {
69 pub fn observe(&mut self, name: &'a str, kind: InferredKind) -> usize {
71 let idx = self.column(name);
72 self.merge(idx, kind);
73 idx
74 }
75
76 pub fn column(&mut self, name: &'a str) -> usize {
78 *self.index.entry(name).or_insert_with(|| {
79 self.names.push(name.to_string());
80 self.kinds.push(InferredKind::Unknown);
81 self.names.len() - 1
82 })
83 }
84
85 pub fn merge(&mut self, idx: usize, kind: InferredKind) {
87 let slot = &mut self.kinds[idx];
89 *slot = slot.merge(kind);
90 }
91
92 pub fn finish(self) -> (Vec<String>, Vec<PropKind>) {
94 let kinds = self
95 .kinds
96 .into_iter()
97 .map(InferredKind::prop_kind)
98 .collect();
99 (self.names, kinds)
100 }
101}