fts_demo/
config.rs

1use rusqlite::{Connection, OptionalExtension};
2use serde::{Deserialize, Serialize};
3use std::time::Duration;
4
5use crate::db;
6
7/// For now, the only configuration option that is used widely is the scale
8/// factor for converting rates into batched quantities.  Eventually, we would
9/// like to provide the server endpoints with pagination instructions rather
10/// than hardcoding the limits. TODO.
11#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
12#[serde(from = "RawConfig", into = "RawConfig")]
13pub struct Config {
14    /// The rate to use for converting rates into batch quantities.
15    pub trade_rate: Duration,
16}
17
18impl Config {
19    /// Retrieves the configuration from the database.
20    pub fn get(conn: &Connection) -> Result<Option<Self>, db::Error> {
21        let response: Option<serde_json::Value> = conn
22            .query_row("select data from config where id = 0 limit 1", (), |row| {
23                row.get(0)
24            })
25            .optional()?;
26
27        if let Some(config_data) = response {
28            let config: Config = serde_json::from_value(config_data)?;
29            Ok(Some(config))
30        } else {
31            Ok(None)
32        }
33    }
34
35    /// Stores the configuration in the database.
36    pub fn set(&self, conn: &Connection) -> Result<(), db::Error> {
37        conn.execute("insert into config (id, data) values (0, ?1) on conflict (id) do update set data = excluded.data", (serde_json::to_value(self)?,))?;
38        Ok(())
39    }
40}
41
42// To seamlessly (de)serialize, we create a "raw" version of of our struct
43// that contains only primitive values. We tell Serde to use the raw version
44// to handle (de)serialization, then call .into() to get our rich version.
45// It's a little verbose, but fairly clean.
46// Note that the u64<>u32 conversion is because JSON serialization does not
47// support 64 bit integers.
48
49#[derive(Serialize, Deserialize)]
50pub struct RawConfig {
51    pub trade_rate: u32,
52}
53
54impl From<RawConfig> for Config {
55    fn from(value: RawConfig) -> Self {
56        Self {
57            trade_rate: Duration::from_secs(value.trade_rate as u64),
58        }
59    }
60}
61
62impl From<Config> for RawConfig {
63    fn from(value: Config) -> Self {
64        Self {
65            trade_rate: value.trade_rate.as_secs() as u32,
66        }
67    }
68}