sprinklers_rs/src/model/program.rs
Alex Mikhalev af0998a719
All checks were successful
continuous-integration/drone/push Build is passing
Implement running sections through MQTT
2020-09-29 23:25:28 -06:00

79 lines
2.1 KiB
Rust

use super::section::SectionId;
use crate::schedule::Schedule;
use serde::{Deserialize, Serialize};
use std::{sync::Arc, time::Duration};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ProgramItem {
pub section_id: SectionId,
#[serde(with = "crate::serde::duration")]
pub duration: Duration,
}
pub type ProgramSequence = Vec<ProgramItem>;
pub type ProgramId = u32;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Program {
pub id: ProgramId,
pub name: String,
pub sequence: ProgramSequence,
pub enabled: bool,
pub schedule: Schedule,
}
mod sql {
use super::{Program, ProgramSequence};
use crate::schedule::Schedule;
use rusqlite::{
types::{FromSql, FromSqlError, FromSqlResult, ValueRef},
Result as SqlResult, Row as SqlRow,
};
use serde::Deserialize;
struct SqlJson<T>(T);
impl<T> SqlJson<T> {
fn into_inner(self) -> T {
self.0
}
}
impl<T> FromSql for SqlJson<T>
where
for<'de> T: Deserialize<'de>,
{
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
if let ValueRef::Text(text) = value {
let deser_value: T = serde_json::from_slice(text)
.map_err(|err| FromSqlError::Other(Box::new(err)))?;
Ok(SqlJson(deser_value))
} else {
Err(FromSqlError::InvalidType)
}
}
}
type SqlProgramSequence = SqlJson<ProgramSequence>;
type SqlSchedule = SqlJson<Schedule>;
impl Program {
pub fn from_sql<'a>(row: &SqlRow<'a>) -> SqlResult<Self> {
Ok(Self {
id: row.get(0)?,
name: row.get(1)?,
sequence: row.get::<_, SqlProgramSequence>(2)?.into_inner(),
enabled: row.get(3)?,
schedule: row.get::<_, SqlSchedule>(4)?.into_inner(),
})
}
}
}
pub type ProgramRef = Arc<Program>;
pub type Programs = im::OrdMap<ProgramId, ProgramRef>;