prehnite_core/settings/
value.rs

1#![doc = "設定の項目値"]
2use crate::db::query;
3use crate::settings::SettingKey;
4use sqlx::SqliteConnection;
5
6#[derive(Clone, Debug)]
7/// 設定の項目値を型付きで表現します。
8pub enum SettingValueType {
9    Bool(Option<bool>),
10    Int(Option<i64>),
11    Float(Option<f64>),
12    String(Option<String>),
13}
14
15impl From<SettingValueType> for Option<bool> {
16    fn from(value: SettingValueType) -> Self {
17        value.bool()
18    }
19}
20
21impl From<SettingValueType> for Option<i64> {
22    fn from(value: SettingValueType) -> Self {
23        value.int()
24    }
25}
26
27impl From<SettingValueType> for Option<String> {
28    fn from(value: SettingValueType) -> Self {
29        value.string()
30    }
31}
32
33impl From<SettingValueType> for Option<f64> {
34    fn from(value: SettingValueType) -> Self {
35        value.float()
36    }
37}
38
39macro_rules! setting_value_type_to_string(
40    ($v:ident) => {
41        $v.map(|v| v.to_string())
42    }
43);
44
45macro_rules! auto_impl_from_non_option(
46    ($($t:ty),*) => {
47        $(
48        impl From<$t> for SettingValueType {
49            fn from(value: $t) -> Self {
50                Some(value).into()
51            }
52        }
53        )*
54    }
55);
56
57auto_impl_from_non_option!(bool, i64, i32, i16, i8, f64, f32, String, &str);
58
59macro_rules! auto_impl_from_option {
60    ($(($t:ty, $req_t:ty, $p:path)),*) => {
61        $(impl From<Option<$t>> for SettingValueType {
62            fn from(value: Option<$t>) -> Self {
63                $p(value.map(|v| v as $req_t))
64            }
65        })*
66    };
67    ($(($t:ty, $p:path)),*)=>{
68        auto_impl_from_option!($(($t, $t, $p)),*);
69    };
70}
71
72auto_impl_from_option!(
73    (bool, SettingValueType::Bool),
74    (i64, SettingValueType::Int),
75    (f64, SettingValueType::Float),
76    (String, SettingValueType::String)
77);
78
79auto_impl_from_option!(
80    (i32, i64, SettingValueType::Int),
81    (i16, i64, SettingValueType::Int),
82    (i8, i64, SettingValueType::Int),
83    (f32, f64, SettingValueType::Float)
84);
85
86impl From<Option<&str>> for SettingValueType {
87    fn from(value: Option<&str>) -> Self {
88        value.map(|v| v.to_string()).into()
89    }
90}
91
92impl SettingValueType {
93    /// 文字列をパースし、設定項目の値に変更します。
94    pub fn converter(&self, value: Option<String>) -> Self {
95        match self {
96            SettingValueType::Bool(_) => value.and_then(|v| v.parse::<bool>().ok()).into(),
97            SettingValueType::Int(_) => value.and_then(|v| v.parse::<i64>().ok()).into(),
98            SettingValueType::Float(_) => value.and_then(|v| v.parse::<f64>().ok()).into(),
99            SettingValueType::String(_) => value.into(),
100        }
101    }
102
103    /// 設定項目の値を設定します。
104    pub fn set(mut self, v: SettingValueType) {
105        self = v;
106    }
107
108    #[tracing::instrument]
109    /// 設定項目を保存します。
110    pub async fn save(
111        &self,
112        conn: &mut SqliteConnection,
113        setting_key: SettingKey,
114    ) -> sqlx::Result<()> {
115        query::update_setting(conn, setting_key, self.clone().to_opt_string()).await
116    }
117
118    /// 設定値を取得します。
119    pub fn get<T>(self) -> Option<T>
120    where
121        Option<T>: From<SettingValueType>,
122    {
123        Option::<T>::from(self)
124    }
125
126    /// 設定値を文字列として取得します。
127    pub fn to_opt_string(self) -> Option<String> {
128        match self {
129            SettingValueType::Bool(v) => setting_value_type_to_string!(v),
130            SettingValueType::Int(v) => setting_value_type_to_string!(v),
131            SettingValueType::Float(v) => setting_value_type_to_string!(v),
132            SettingValueType::String(v) => v,
133        }
134    }
135
136    /// [`bool`]の設定値を取得します。[`bool`]以外の場合は[`None`]を返します。
137    fn bool(self) -> Option<bool> {
138        if let Self::Bool(v) = self { v } else { None }
139    }
140
141    /// [`i64`]の設定値を取得します。[`i64`]以外の場合は[`None`]を返します。
142    fn int(self) -> Option<i64> {
143        if let Self::Int(v) = self { v } else { None }
144    }
145
146    /// [`String`]の設定値を取得します。[`String`]以外の場合は[`None`]を返します。
147    fn string(self) -> Option<String> {
148        if let Self::String(v) = self { v } else { None }
149    }
150
151    /// [`f64`]の設定値を取得します。[`f64`]以外の場合は[`None`]を返します。
152    fn float(self) -> Option<f64> {
153        if let Self::Float(v) = self { v } else { None }
154    }
155}