use crate::db::errors::DatabaseError; use crate::db::{DbController, DbRelay, DbSchedule}; use crate::types::ControllerUid; use futures::executor; use serde_derive::{Deserialize, Serialize}; use sqlx::pool::PoolConnection; use sqlx::Sqlite; pub trait FromDbModel { type DbModel: Clone; fn from_db_model( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, ) -> Result<Self, DatabaseError> where Self: Sized; } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Schedule { #[serde(flatten)] pub s: DbSchedule, pub tags: Vec<String>, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Relay { #[serde(flatten)] pub r: DbRelay, pub controller: DbController, pub controller_id: ControllerUid, pub tags: Vec<String>, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Controller { #[serde(flatten)] pub c: DbController, pub relays: Vec<Relay>, } impl FromDbModel for Schedule { type DbModel = DbSchedule; fn from_db_model( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, ) -> Result<Self, DatabaseError> { let schedule = db_model.clone(); let tags = executor::block_on(schedule.get_tags(conn))?; Ok(Schedule { s: schedule, tags }) } } impl FromDbModel for Relay { type DbModel = DbRelay; fn from_db_model( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, ) -> Result<Self, DatabaseError> { let relay = db_model.clone(); let controller = executor::block_on(relay.get_controller(conn))?; let controller_id = controller.uid.clone(); let tags = executor::block_on(relay.get_tags(conn))?; Ok(Relay { r: relay, controller, controller_id, tags, }) } } impl FromDbModel for Controller { type DbModel = DbController; fn from_db_model( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, ) -> Result<Self, DatabaseError> { let relays_db = executor::block_on(db_model.get_relays(conn))?; let relays = convert_db_list(conn, relays_db)?; Ok(Controller { c: db_model, relays, }) } } pub fn convert_db_list<T: FromDbModel>( conn: &mut PoolConnection<Sqlite>, db_models: Vec<T::DbModel>, ) -> Result<Vec<T>, DatabaseError> { let mut result: Vec<T> = Vec::new(); db_models.into_iter().try_for_each(|s| { let new = T::from_db_model(conn, s); match new { Ok(new) => { result.push(new); Ok(()) } Err(e) => Err(e), } })?; Ok(result) }