1use std::{
2 collections::{HashMap, HashSet},
3 fmt::{self, Display, Formatter},
4 ops::{Deref, RangeInclusive},
5 time::Duration,
6};
7
8pub use settings_schema_derive::SettingsSchema;
9
10pub use serde::{Deserialize, Serialize};
12pub use serde_json::to_value as to_json_value;
13
14#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
15pub struct Percentage(f32);
16
17impl Percentage {
18 pub fn new(value: u8) -> Self {
19 Self(value as f32 / 100.0)
20 }
21
22 pub fn new_normalized(value: f32) -> Self {
23 Self(value)
24 }
25}
26
27impl From<u8> for Percentage {
28 fn from(value: u8) -> Self {
29 Self(value as f32)
30 }
31}
32
33impl From<f32> for Percentage {
34 fn from(value: f32) -> Self {
35 Self(value)
36 }
37}
38
39impl Deref for Percentage {
40 type Target = f32;
41
42 fn deref(&self) -> &f32 {
43 &self.0
44 }
45}
46
47impl Display for Percentage {
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 write!(f, "{}%", (self.0 * 100.0) as u8)
50 }
51}
52
53#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
56pub enum Switch<T> {
57 Enabled(T),
58 Disabled,
59}
60
61impl<T> Switch<T> {
62 pub fn as_option(&self) -> Option<&T> {
63 match self {
64 Self::Enabled(t) => Some(t),
65 Self::Disabled => None,
66 }
67 }
68
69 pub fn into_option(self) -> Option<T> {
70 match self {
71 Self::Enabled(t) => Some(t),
72 Self::Disabled => None,
73 }
74 }
75}
76
77#[derive(Serialize, Deserialize, Clone, Debug)]
80pub struct OptionalDefault<C> {
81 pub set: bool,
82 pub content: C,
83}
84
85#[derive(Serialize, Deserialize, Clone, Debug)]
88pub struct SwitchDefault<C> {
89 pub enabled: bool,
90 pub content: C,
91}
92
93#[derive(Serialize, Deserialize, Clone, Debug)]
96pub struct VectorDefault<T> {
97 pub element: T,
98 pub content: Vec<T>,
99}
100
101#[derive(Serialize, Deserialize, Clone, Debug)]
104pub struct DictionaryDefault<T> {
105 pub key: String,
106 pub value: T,
107 pub content: Vec<(String, T)>,
108}
109
110#[derive(Serialize, Deserialize, Clone, Debug)]
112pub enum NumericGuiType {
113 Slider {
114 range: RangeInclusive<f64>,
115 step: Option<f64>,
116 logarithmic: bool,
117 },
118 TextBox,
119}
120
121#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
122pub enum NumberType {
123 UnsignedInteger,
124 SignedInteger,
125 Float,
126}
127
128#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
130pub enum ChoiceControlType {
131 Dropdown,
132 ButtonGroup,
133}
134
135#[derive(Serialize, Deserialize, Clone, Debug)]
136pub struct SchemaEntry<T> {
137 pub name: String,
138 pub strings: HashMap<String, String>,
139 pub flags: HashSet<String>,
140 pub content: T,
141}
142
143#[non_exhaustive]
147#[derive(Serialize, Deserialize, Clone, Debug)]
148pub enum SchemaNode {
149 Section(Vec<SchemaEntry<SchemaNode>>),
150 Choice {
151 default: String,
152 variants: Vec<SchemaEntry<Option<SchemaNode>>>,
153 gui: Option<ChoiceControlType>,
154 },
155 Optional {
156 default_set: bool,
157 content: Box<SchemaNode>,
158 },
159 Switch {
160 default_enabled: bool,
161 content: Box<SchemaNode>,
162 },
163 Boolean {
164 default: bool,
165 },
166 Number {
167 default: f64,
168 ty: NumberType,
169 gui: NumericGuiType,
170 suffix: Option<String>,
171 },
172 Range {
173 default: [f64; 2],
174 ty: NumberType,
175 gui: NumericGuiType,
176 suffix: Option<String>,
177 },
178 Percentage {
179 default_normalized: f32,
180 range_normalized: Option<RangeInclusive<f32>>,
181 },
182 Duration {
183 default: Duration,
184 range: RangeInclusive<Duration>,
185 logarithmic: bool,
186 },
187 Text {
188 default: String,
189 },
190 Array(Vec<SchemaNode>),
191 Vector {
192 default_element: Box<SchemaNode>,
193 default: serde_json::Value,
194 },
195 Dictionary {
196 default_key: String,
197 default_value: Box<SchemaNode>,
198 default: serde_json::Value,
199 },
200}