mirror of
https://github.com/alvierahman90/rabbit.git
synced 2024-12-15 11:01:59 +00:00
json serialisation
This commit is contained in:
parent
e8332ee093
commit
eebbef6782
@ -12,7 +12,10 @@ default = ["console_error_panic_hook"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2.84"
|
wasm-bindgen = "0.2.84"
|
||||||
chrono = { version = "0.4.31", features = [ "clock" ] }
|
chrono = { version = "0.4.31", features = [ "clock", "serde" ] }
|
||||||
|
serde = { version = "1.0", features = [ "derive" ] }
|
||||||
|
serde_json = { version = "1.0", features = [ "std" ] }
|
||||||
|
serde_with = { version = "3.4.0", features = [ "std", "chrono_0_4", "json" ] }
|
||||||
|
|
||||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||||
# logging them with `console.error`. This is great for development, but requires
|
# logging them with `console.error`. This is great for development, but requires
|
||||||
|
37
src/db.rs
Normal file
37
src/db.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
pub mod json;
|
||||||
|
|
||||||
|
use crate::models::*;
|
||||||
|
use std::io;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Generic(String),
|
||||||
|
FsIo(String),
|
||||||
|
Json(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(e: io::Error) -> Self {
|
||||||
|
Self::FsIo(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::Error> for Error {
|
||||||
|
fn from(e: serde_json::Error) -> Self{
|
||||||
|
Self::Json(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Storage {
|
||||||
|
fn add_category(&mut self, category: NewCategory) -> Result<i32, Error>;
|
||||||
|
fn add_series(&mut self, category_id: i32, series: NewSeries) -> Result<i32, Error>;
|
||||||
|
fn add_series_point(&mut self, category_id: i32, series_id: i32, series_point: NewSeriesPoint) -> Result<i32, Error>;
|
||||||
|
//fn add_user(&mut self, id: i32, user: NewUser) -> Result<User, Error>;
|
||||||
|
fn get_category(&self, id: i32) -> Option<Category>;
|
||||||
|
//fn get_series(&self, id: i32) -> Result<Series, Error>;
|
||||||
|
//fn get_user(&self, id: i32) -> Result<User, Error>;
|
||||||
|
//fn update_category(&mut self, id: i32, changeset: CategoryChangeset) -> Result<(), Error>;
|
||||||
|
//fn update_series(&mut self, id: i32, changeset: SeriesChangeset) -> Result<(), Error>;
|
||||||
|
//fn update_user(&mut self, id: i32, changeset: UserChangeset) -> Result<(), Error>;
|
||||||
|
}
|
136
src/db/json.rs
Normal file
136
src/db/json.rs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct JsonDb {
|
||||||
|
pub value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// JsonDb is single user.
|
||||||
|
impl JsonDb {
|
||||||
|
pub fn new(value: Option<String>) -> Self {
|
||||||
|
match value {
|
||||||
|
Some(value) => JsonDb { value },
|
||||||
|
None => JsonDb { value: String::from("[]") },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self) -> Result<Vec<Category>, Error> {
|
||||||
|
match serde_json::from_str::<Vec<Category>>(&self.value) {
|
||||||
|
Ok(d) => Ok(d),
|
||||||
|
Err(e) => Err(Error::from(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save(&mut self, data: Vec<Category>) -> Result<(), Error> {
|
||||||
|
let data = serde_json::to_string_pretty(&data);
|
||||||
|
match data {
|
||||||
|
Ok(d) => {
|
||||||
|
self.value = d;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(e) => Err(Error::from(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Storage for JsonDb {
|
||||||
|
fn add_category(&mut self, category: NewCategory) -> Result<i32, Error> {
|
||||||
|
let mut max_id = 1;
|
||||||
|
let mut data = self.load()?;
|
||||||
|
for cat in data.iter().clone() {
|
||||||
|
if cat.id > max_id {
|
||||||
|
max_id = cat.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let created = Category::new(max_id+1, category);
|
||||||
|
data.push(created);
|
||||||
|
self.save(data)?;
|
||||||
|
|
||||||
|
Ok(max_id + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_series(&mut self, category_id: i32, series: NewSeries) -> Result<i32, Error> {
|
||||||
|
let mut max_id = 1;
|
||||||
|
let mut cat: Option<&mut Category> = None;
|
||||||
|
|
||||||
|
let mut data = self.load()?;
|
||||||
|
for cat_opt in data.iter_mut() {
|
||||||
|
if cat_opt.id == category_id {
|
||||||
|
cat = Some(cat_opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let None = cat {
|
||||||
|
return Err(Error::Generic ("Unable to find category".to_owned()));
|
||||||
|
}
|
||||||
|
let cat = cat.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
for series in cat.series.iter().clone() {
|
||||||
|
if series.id > max_id {
|
||||||
|
max_id = series.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let created = Series::new(max_id+1, series);
|
||||||
|
cat.series.push(created);
|
||||||
|
self.save(data)?;
|
||||||
|
|
||||||
|
Ok(max_id + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_series_point(&mut self, category_id: i32, series_id: i32, series_point: NewSeriesPoint) -> Result<i32, Error> {
|
||||||
|
let mut max_id = 1;
|
||||||
|
let mut cat: Option<&mut Category> = None;
|
||||||
|
let mut series: Option<&mut Series> = None;
|
||||||
|
|
||||||
|
let mut data = self.load()?;
|
||||||
|
for cat_opt in data.iter_mut() {
|
||||||
|
if cat_opt.id == category_id {
|
||||||
|
cat = Some(cat_opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let None = cat {
|
||||||
|
return Err(Error::Generic ("Unable to find category".to_owned()));
|
||||||
|
}
|
||||||
|
let cat = cat.unwrap();
|
||||||
|
|
||||||
|
for series_opt in cat.series.iter_mut() {
|
||||||
|
if series_opt.id == series_id {
|
||||||
|
series = Some(series_opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let None = series {
|
||||||
|
return Err(Error::Generic ("Unable to find series".to_owned()));
|
||||||
|
}
|
||||||
|
let series: &mut Series = series.unwrap();
|
||||||
|
|
||||||
|
for point in series.points.iter().clone() {
|
||||||
|
if point.id > max_id {
|
||||||
|
max_id = point.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let created = SeriesPoint::new(max_id + 1, series_point);
|
||||||
|
series.points.push(created);
|
||||||
|
self.save(data)?;
|
||||||
|
|
||||||
|
Ok(max_id + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_category(&self, id: i32) -> Option<Category> {
|
||||||
|
let data = self.load().ok()?;
|
||||||
|
|
||||||
|
for cat_opt in data {
|
||||||
|
if cat_opt.id == id {
|
||||||
|
return Some(cat_opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
mod utils;
|
mod utils;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
pub mod db;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
pub mod category;
|
mod category;
|
||||||
pub mod series;
|
mod series;
|
||||||
pub mod series_point;
|
mod series_point;
|
||||||
pub mod series_type;
|
mod series_type;
|
||||||
|
mod user;
|
||||||
|
|
||||||
pub use category::*;
|
pub use category::*;
|
||||||
pub use series::*;
|
pub use series::*;
|
||||||
pub use series_point::*;
|
pub use series_point::*;
|
||||||
pub use series_type::*;
|
pub use series_type::*;
|
||||||
|
pub use user::*;
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
use crate::models::Series;
|
use crate::models::Series;
|
||||||
|
use serde::{ Serialize, Deserialize };
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Category {
|
pub struct Category {
|
||||||
id: i32,
|
pub id: i32,
|
||||||
name: String,
|
pub name: String,
|
||||||
series: Vec<Series>,
|
pub series: Vec<Series>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Category {
|
impl Category {
|
||||||
pub fn new(id: i32, name: String) -> Category {
|
pub fn new(id: i32, new: NewCategory) -> Category {
|
||||||
Category {
|
Category {
|
||||||
id,
|
id,
|
||||||
name,
|
name: new.name,
|
||||||
series: vec![],
|
series: new.series,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,3 +21,13 @@ impl Category {
|
|||||||
self.series.push(series);
|
self.series.push(series);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CategoryChangeset {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub series: Option<Vec<Series>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NewCategory {
|
||||||
|
pub name: String,
|
||||||
|
pub series: Vec<Series>,
|
||||||
|
}
|
||||||
|
@ -1,23 +1,27 @@
|
|||||||
use chrono;
|
use chrono;
|
||||||
use super::series_point::SeriesPoint;
|
use super::series_point::SeriesPoint;
|
||||||
|
use serde::{ Serialize, Deserialize };
|
||||||
|
use serde_with;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[serde_with::serde_as]
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Series {
|
pub struct Series {
|
||||||
id: i32,
|
pub id: i32,
|
||||||
name: String,
|
pub name: String,
|
||||||
repeat: chrono::Duration,
|
#[serde_as(as = "serde_with::DurationSeconds<i64>")]
|
||||||
good: bool,
|
pub repeat: chrono::Duration,
|
||||||
points: Vec<SeriesPoint>,
|
pub good: bool,
|
||||||
|
pub points: Vec<SeriesPoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Series {
|
impl Series {
|
||||||
pub fn new(id: i32, name: String, repeat: chrono::Duration, good: bool) -> Series {
|
pub fn new(id: i32, series: NewSeries) -> Series {
|
||||||
Series {
|
Series {
|
||||||
id,
|
id,
|
||||||
name,
|
name: series.name,
|
||||||
repeat,
|
repeat: series.repeat,
|
||||||
good,
|
good: series.good,
|
||||||
points: vec![],
|
points: series.points,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,3 +29,17 @@ impl Series {
|
|||||||
self.points.push(point);
|
self.points.push(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SeriesChangeset {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub repeat: Option<chrono::Duration>,
|
||||||
|
pub good: Option<bool>,
|
||||||
|
pub points: Option<Vec<SeriesPoint>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NewSeries {
|
||||||
|
pub name: String,
|
||||||
|
pub repeat: chrono::Duration,
|
||||||
|
pub good: bool,
|
||||||
|
pub points: Vec<SeriesPoint>,
|
||||||
|
}
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
use chrono;
|
use chrono;
|
||||||
use super::series_type::SeriesType;
|
use super::series_type::SeriesType;
|
||||||
|
use serde::{ Serialize, Deserialize };
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SeriesPoint {
|
pub struct SeriesPoint {
|
||||||
id: i32,
|
pub id: i32,
|
||||||
timestamp: chrono::NaiveDateTime,
|
pub timestamp: chrono::NaiveDateTime,
|
||||||
value: SeriesType,
|
pub value: SeriesType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SeriesPoint {
|
impl SeriesPoint {
|
||||||
pub fn new(id: i32, timestamp: chrono::NaiveDateTime, value: SeriesType) -> SeriesPoint {
|
pub fn new(id: i32, new: NewSeriesPoint) -> SeriesPoint {
|
||||||
SeriesPoint {
|
SeriesPoint {
|
||||||
id,
|
id,
|
||||||
timestamp,
|
timestamp: new.timestamp,
|
||||||
value
|
value: new.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NewSeriesPoint {
|
||||||
|
pub timestamp: chrono::NaiveDateTime,
|
||||||
|
pub value: SeriesType,
|
||||||
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#[derive(Debug)]
|
use serde::{ Serialize, Deserialize };
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum SeriesType {
|
pub enum SeriesType {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Count(u32),
|
Count(u32),
|
||||||
|
18
src/models/user.rs
Normal file
18
src/models/user.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use serde::{ Serialize, Deserialize };
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct User {
|
||||||
|
id: i32,
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UserChangeset {
|
||||||
|
name: Option<String>,
|
||||||
|
email: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NewUser {
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user