vin_decode/data.rs
1//! Internal rkyv archive types for the lookup tables.
2//!
3//! These types are exposed publicly only when the `build` feature is enabled,
4//! since the build pipeline needs to construct them. End users of the decoder
5//! never see these — they go through [`crate::Decoder`] / [`crate::Catalog`].
6
7use rkyv::{
8 Archive, Deserialize, Serialize,
9 api::high::{HighDeserializer, HighSerializer},
10 rancor::Error as RkyvError,
11 ser::allocator::ArenaHandle,
12 util::AlignedVec,
13};
14
15/// Marker trait for types that can be rkyv-deserialized via the high-level helpers.
16pub trait RkyvDe<T>: Deserialize<T, HighDeserializer<RkyvError>> {}
17
18/// Marker trait for types that can be rkyv-serialized via the high-level helpers.
19pub trait RkyvSer:
20 for<'a> Serialize<HighSerializer<AlignedVec, ArenaHandle<'a>, RkyvError>>
21{
22}
23
24/// Trait that maps a row type to its on-disk file name (sans extension).
25pub trait Saveable {
26 /// Base name for the `.fst`/`.bin` file pair on disk.
27 fn base_name() -> &'static str;
28}
29
30/// Single make-name row, keyed by WMI in the `wmi_make` table.
31///
32/// Country and region are populated when the WMI was sourced from KBA / vPIC /
33/// merged datasets that carried plant origin metadata. Empty string means the
34/// upstream source did not record this field.
35#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
36pub struct MakeRow {
37 /// Make name as it appears in the source (e.g. `"Honda"`).
38 pub name: String,
39 /// Plant country (uppercased canonical form, e.g. `"GERMANY"`).
40 pub country: String,
41 /// Region bucket (`"EUROPE"`, `"NORTH_AMERICA"`, `"ASIA"`, `"OCEANIA"`,
42 /// `"SOUTH_AMERICA"`, `"AFRICA"`).
43 pub region: String,
44}
45impl RkyvSer for MakeRow {}
46impl RkyvDe<MakeRow> for ArchivedMakeRow {}
47impl Saveable for MakeRow {
48 fn base_name() -> &'static str {
49 "wmi_make"
50 }
51}
52
53/// Brand → model index row with year range, sourced from the EU/global rip.
54#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
55pub struct EuModelRow {
56 /// Model name (uppercase canonical, e.g. `"FABIA"`, `"OCTAVIA RS"`).
57 pub name: String,
58 /// First production year known for this model. `0` if unknown.
59 pub first_year: u16,
60 /// Last production year known for this model. `0` if unknown.
61 pub last_year: u16,
62}
63impl RkyvSer for EuModelRow {}
64impl RkyvDe<EuModelRow> for ArchivedEuModelRow {}
65impl Saveable for EuModelRow {
66 fn base_name() -> &'static str {
67 "eu_brand_models"
68 }
69}
70
71/// Engine variant row, keyed by `BRAND` in the engine catalog. Filter by
72/// `model` in user code (or use `Catalog::engines_for(brand, model)`).
73#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
74pub struct EngineRow {
75 /// Model name this engine belongs to (e.g. `"FABIA"`, `"OCTAVIA RS"`).
76 pub model: String,
77 /// Production year of this engine variant.
78 pub year: u16,
79 /// Engine variant display name (e.g. `"2.0 TDI 150hp"`).
80 pub name: String,
81 /// Number of cylinders / configuration string (e.g. `"4"`, `"V6"`, `"I4"`).
82 pub cylinders: String,
83 /// Displacement in cubic centimetres.
84 pub displacement_cm3: u32,
85 /// Continuous power output in kilowatts.
86 pub power_kw: u32,
87 /// Continuous power output in metric horsepower.
88 pub power_hp: u32,
89 /// Peak torque in newton-metres.
90 pub torque_nm: u32,
91 /// Fuel name as published (e.g. `"Gasoline"`, `"Diesel"`, `"Electric"`).
92 pub fuel: String,
93 /// Drive type (e.g. `"Front Wheel Drive"`, `"All Wheel Drive"`).
94 pub drive: String,
95 /// Gearbox description (e.g. `"6-Speed Manual"`).
96 pub gearbox: String,
97}
98impl RkyvSer for EngineRow {}
99impl RkyvDe<EngineRow> for ArchivedEngineRow {}
100impl Saveable for EngineRow {
101 fn base_name() -> &'static str {
102 "eu_engines"
103 }
104}
105
106/// Schema identifier row, keyed by WMI in the `wmi_schema` table.
107#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
108pub struct SchemaRow {
109 /// Schema identifier string (vPIC schema_id column).
110 pub id: String,
111}
112impl RkyvSer for SchemaRow {}
113impl RkyvDe<SchemaRow> for ArchivedSchemaRow {}
114impl Saveable for SchemaRow {
115 fn base_name() -> &'static str {
116 "wmi_schema"
117 }
118}
119
120/// Single lookup row, keyed by schema id in the `schema_lookup` table.
121#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
122pub struct LookupRow {
123 /// VIN pattern with optional `|VIS` metadata suffix.
124 pub pattern: String,
125 /// vPIC element name (e.g. `"Model"`, `"BodyClass"`, `"FuelTypePrimary"`).
126 pub element: String,
127 /// Resolved attribute value to apply when this pattern matches.
128 pub value: String,
129 /// Element weight — higher wins when multiple patterns match the same element.
130 pub weight: u32,
131}
132impl RkyvSer for LookupRow {}
133impl RkyvDe<LookupRow> for ArchivedLookupRow {}
134impl Saveable for LookupRow {
135 fn base_name() -> &'static str {
136 "schema_lookup"
137 }
138}
139
140/// Single model-name row, keyed by uppercase make in the `make_models` reverse index.
141#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
142pub struct ModelRow {
143 /// Model name as it appears in vPIC patterns.
144 pub name: String,
145}
146impl RkyvSer for ModelRow {}
147impl RkyvDe<ModelRow> for ArchivedModelRow {}
148impl Saveable for ModelRow {
149 fn base_name() -> &'static str {
150 "make_models"
151 }
152}
153
154/// Per-VIN rule keyed by 3-char WMI in the `wmi_rules` table. Each rule
155/// supplies a VDS-prefix `remainder` (matched against `vin[3..]`) plus optional
156/// `make` / `model` overrides. Empty strings mean "leave the existing value".
157///
158/// The build pipeline pre-sorts a WMI's rules by `remainder.len()` DESC so the
159/// decoder can do longest-prefix-match by walking the list and picking the
160/// first hit. A row with empty `remainder` acts as a fallback that fires for
161/// any VIN sharing the WMI (handy for fixing mislabeled WMI → make mappings
162/// from upstream sources without losing valid model-specific overrides).
163#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
164pub struct VinRuleRow {
165 /// VDS prefix appended after the WMI (e.g. `"ZZZ8X"`); empty matches all.
166 pub remainder: String,
167 /// Make override (uppercase canonical, matches `eu_brand_models` keys);
168 /// empty string means keep the make resolved from `wmi_make`.
169 pub make: String,
170 /// Model override; empty string means leave model unset (let pattern
171 /// decode handle it).
172 pub model: String,
173}
174impl RkyvSer for VinRuleRow {}
175impl RkyvDe<VinRuleRow> for ArchivedVinRuleRow {}
176impl Saveable for VinRuleRow {
177 fn base_name() -> &'static str {
178 "wmi_rules"
179 }
180}