use rkyv::{
Archive, Deserialize, Serialize,
api::high::{HighDeserializer, HighSerializer},
rancor::Error as RkyvError,
ser::allocator::ArenaHandle,
util::AlignedVec,
};
use crate::types::{BodyType, DriveType, FuelType, Transmission};
pub trait RkyvDe<T>: Deserialize<T, HighDeserializer<RkyvError>> {}
pub trait RkyvSer:
for<'a> Serialize<HighSerializer<AlignedVec, ArenaHandle<'a>, RkyvError>>
{
}
pub trait Saveable {
fn base_name() -> &'static str;
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct MakeRow {
pub name: String,
pub country: String,
pub region: String,
}
impl RkyvSer for MakeRow {}
impl RkyvDe<MakeRow> for ArchivedMakeRow {}
impl Saveable for MakeRow {
fn base_name() -> &'static str {
"wmi_make"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct EuModelRow {
pub name: String,
pub first_year: u16,
pub last_year: u16,
}
impl RkyvSer for EuModelRow {}
impl RkyvDe<EuModelRow> for ArchivedEuModelRow {}
impl Saveable for EuModelRow {
fn base_name() -> &'static str {
"eu_brand_models"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct EngineRow {
pub model: String,
pub year: u16,
pub name: String,
pub cylinders: String,
pub displacement_cm3: u32,
pub power_kw: u32,
pub power_hp: u32,
pub torque_nm: u32,
pub fuel: String,
pub drive: String,
pub gearbox: String,
}
impl RkyvSer for EngineRow {}
impl RkyvDe<EngineRow> for ArchivedEngineRow {}
impl Saveable for EngineRow {
fn base_name() -> &'static str {
"eu_engines"
}
}
impl EngineRow {
pub fn fuel_type(&self) -> FuelType {
FuelType::parse(&self.fuel)
}
pub fn drive_type(&self) -> DriveType {
DriveType::parse(&self.drive)
}
pub fn transmission(&self) -> Transmission {
Transmission::parse(&self.gearbox)
}
pub fn gearbox_speeds(&self) -> Option<u8> {
let bytes = self.gearbox.as_bytes();
let mut i = 0;
while i < bytes.len() && !bytes[i].is_ascii_digit() {
i += 1;
}
let start = i;
while i < bytes.len() && bytes[i].is_ascii_digit() {
i += 1;
}
if start == i {
None
} else {
self.gearbox[start..i].parse().ok()
}
}
}
#[cfg(test)]
mod engine_tests {
use super::*;
fn row(fuel: &str, drive: &str, gearbox: &str) -> EngineRow {
EngineRow {
model: "FABIA".into(),
year: 2020,
name: "1.0 TSI".into(),
cylinders: "3".into(),
displacement_cm3: 999,
power_kw: 70,
power_hp: 95,
torque_nm: 175,
fuel: fuel.into(),
drive: drive.into(),
gearbox: gearbox.into(),
}
}
#[test]
fn engine_typed_accessors() {
let r = row("Gasoline", "Front Wheel Drive", "6-Speed Manual");
assert_eq!(r.fuel_type(), FuelType::Gasoline);
assert_eq!(r.drive_type(), DriveType::Fwd);
assert_eq!(r.transmission(), Transmission::Manual);
assert_eq!(r.gearbox_speeds(), Some(6));
let ev = row("Electric", "All Wheel Drive", "1-Speed");
assert_eq!(ev.fuel_type(), FuelType::Electric);
assert_eq!(ev.drive_type(), DriveType::Awd);
assert_eq!(ev.transmission(), Transmission::SingleSpeed);
assert_eq!(ev.gearbox_speeds(), Some(1));
let cvt = row("Hybrid", "Front Wheel Drive", "CVT");
assert_eq!(cvt.transmission(), Transmission::Cvt);
assert_eq!(cvt.gearbox_speeds(), None);
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct BodyRow {
pub model: String,
pub bodies: Vec<BodyType>,
}
impl RkyvSer for BodyRow {}
impl RkyvDe<BodyRow> for ArchivedBodyRow {}
impl Saveable for BodyRow {
fn base_name() -> &'static str {
"eu_body"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct SchemaRow {
pub id: String,
}
impl RkyvSer for SchemaRow {}
impl RkyvDe<SchemaRow> for ArchivedSchemaRow {}
impl Saveable for SchemaRow {
fn base_name() -> &'static str {
"wmi_schema"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct LookupRow {
pub pattern: String,
pub element: String,
pub value: String,
pub weight: u32,
}
impl RkyvSer for LookupRow {}
impl RkyvDe<LookupRow> for ArchivedLookupRow {}
impl Saveable for LookupRow {
fn base_name() -> &'static str {
"schema_lookup"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct ModelRow {
pub name: String,
}
impl RkyvSer for ModelRow {}
impl RkyvDe<ModelRow> for ArchivedModelRow {}
impl Saveable for ModelRow {
fn base_name() -> &'static str {
"make_models"
}
}
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct VinRuleRow {
pub remainder: String,
pub make: String,
pub model: String,
}
impl RkyvSer for VinRuleRow {}
impl RkyvDe<VinRuleRow> for ArchivedVinRuleRow {}
impl Saveable for VinRuleRow {
fn base_name() -> &'static str {
"wmi_rules"
}
}