use crate::error::SqliteConfigError; use domain::{DisplayHint, DisplayHintKind, KeyMapping, WidgetConfig}; use sqlx::Row; use sqlx::sqlite::SqliteRow; pub fn display_hint_to_str(hint: &DisplayHint) -> &'static str { match hint.kind { DisplayHintKind::IconValue => "icon_value", DisplayHintKind::TextBlock => "text_block", DisplayHintKind::KeyValue => "key_value", } } fn display_hint_from_str(s: &str) -> Result { match s { "icon_value" => Ok(DisplayHint::new(DisplayHintKind::IconValue)), "text_block" => Ok(DisplayHint::new(DisplayHintKind::TextBlock)), "key_value" => Ok(DisplayHint::new(DisplayHintKind::KeyValue)), _ => Err(SqliteConfigError::Serialization(format!( "unknown display hint: {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 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: display_hint_from_str(&hint_str)?, data_source_id: ds_id as u16, mappings: mappings_from_json(&mappings_json)?, max_data_size: max_size as u16, }) }