use crate::error::SqliteConfigError; use domain::{DisplayHint, DisplayHintKind, HAlign, KeyMapping, VAlign, WidgetConfig}; use sqlx::Row; use sqlx::sqlite::SqliteRow; pub fn display_hint_kind_to_str(hint: &DisplayHint) -> &'static str { match hint.kind { DisplayHintKind::IconValue => "icon_value", DisplayHintKind::TextBlock => "text_block", DisplayHintKind::KeyValue => "key_value", } } pub fn h_align_to_str(a: HAlign) -> &'static str { match a { HAlign::Left => "left", HAlign::Center => "center", HAlign::Right => "right", } } pub fn v_align_to_str(a: VAlign) -> &'static str { match a { VAlign::Top => "top", VAlign::Middle => "middle", VAlign::Bottom => "bottom", } } fn hint_kind_from_str(s: &str) -> Result { match s { "icon_value" => Ok(DisplayHintKind::IconValue), "text_block" => Ok(DisplayHintKind::TextBlock), "key_value" => Ok(DisplayHintKind::KeyValue), _ => Err(SqliteConfigError::Serialization(format!( "unknown display hint: {s}" ))), } } fn h_align_from_str(s: &str) -> Result { match s { "left" => Ok(HAlign::Left), "center" => Ok(HAlign::Center), "right" => Ok(HAlign::Right), _ => Err(SqliteConfigError::Serialization(format!( "unknown h_align: {s}" ))), } } fn v_align_from_str(s: &str) -> Result { match s { "top" => Ok(VAlign::Top), "middle" => Ok(VAlign::Middle), "bottom" => Ok(VAlign::Bottom), _ => Err(SqliteConfigError::Serialization(format!( "unknown v_align: {s}" ))), } } pub fn mappings_to_json(mappings: &[KeyMapping]) -> Result { let entries: Vec = mappings .iter() .map(|m| { serde_json::json!({ "source_path": m.source_path, "target_key": m.target_key, }) }) .collect(); serde_json::to_string(&entries).map_err(|e| SqliteConfigError::Serialization(e.to_string())) } fn mappings_from_json(json: &str) -> Result, SqliteConfigError> { let entries: Vec = serde_json::from_str(json).map_err(|e| SqliteConfigError::Serialization(e.to_string()))?; entries .iter() .map(|v| { Ok(KeyMapping { source_path: v["source_path"] .as_str() .ok_or_else(|| SqliteConfigError::Serialization("missing source_path".into()))? .into(), target_key: v["target_key"] .as_str() .ok_or_else(|| SqliteConfigError::Serialization("missing target_key".into()))? .into(), }) }) .collect() } pub fn widget_from_row(row: &SqliteRow) -> Result { let id: i64 = row.get("id"); let name: String = row.get("name"); let hint_str: String = row.get("display_hint"); let h_align_str: String = row.get("h_align"); let v_align_str: String = row.get("v_align"); let ds_id: i64 = row.get("data_source_id"); let mappings_json: String = row.get("mappings"); let max_size: i64 = row.get("max_data_size"); Ok(WidgetConfig { id: id as u16, name, display_hint: DisplayHint { kind: hint_kind_from_str(&hint_str)?, h_align: h_align_from_str(&h_align_str)?, v_align: v_align_from_str(&v_align_str)?, }, data_source_id: ds_id as u16, mappings: mappings_from_json(&mappings_json)?, max_data_size: max_size as u16, }) }