Alex Mikhalev
4 years ago
23 changed files with 156 additions and 129 deletions
@ -1,5 +1,6 @@
@@ -1,5 +1,6 @@
|
||||
[workspace] |
||||
|
||||
members = [ |
||||
"sprinklers_core", |
||||
"sprinklers_rs" |
||||
] |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[package] |
||||
name = "sprinklers_core" |
||||
version = "0.1.0" |
||||
authors = ["Alex Mikhalev <alexmikhalevalex@gmail.com>"] |
||||
edition = "2018" |
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
||||
[dependencies] |
||||
chrono = { version = "0.4.15" } |
||||
serde = { version = "1.0.116", features = ["derive"] } |
||||
im = "15.0.0" |
||||
tracing = { version = "0.1.19" } |
||||
|
||||
[dev-dependencies] |
||||
serde_json = "1.0.57" |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
pub mod model; |
||||
pub mod schedule; |
||||
pub mod serde; |
||||
pub mod section_interface; |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
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_secs")] |
||||
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, |
||||
} |
||||
|
||||
pub type ProgramRef = Arc<Program>; |
||||
|
||||
pub type Programs = im::OrdMap<ProgramId, ProgramRef>; |
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
||||
|
||||
pub mod duration { |
||||
pub mod duration_secs { |
||||
use super::*; |
||||
use std::time::Duration; |
||||
|
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
use sprinklers_core::{ |
||||
model::{Program, ProgramSequence}, |
||||
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>; |
||||
|
||||
pub fn from_sql<'a>(row: &SqlRow<'a>) -> SqlResult<Program> { |
||||
Ok(Program { |
||||
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(), |
||||
}) |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
use sprinklers_core::model::Section; |
||||
|
||||
use rusqlite::{Error as SqlError, Row as SqlRow, ToSql}; |
||||
|
||||
pub fn from_sql<'a>(row: &SqlRow<'a>) -> Result<Section, SqlError> { |
||||
Ok(Section { |
||||
id: row.get(0)?, |
||||
name: row.get(1)?, |
||||
interface_id: row.get(2)?, |
||||
}) |
||||
} |
||||
|
||||
#[allow(dead_code)] |
||||
pub fn as_sql(section: &Section) -> Vec<&dyn ToSql> { |
||||
vec![§ion.id, §ion.name, §ion.interface_id] |
||||
} |
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
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>; |
Loading…
Reference in new issue