veloren_server/settings/
server_description.rs1use super::{MIGRATION_UPGRADE_GUARANTEE, SERVER_DESCRIPTION_FILENAME as FILENAME};
6use crate::settings::editable::{EditableSetting, Version};
7use core::convert::{Infallible, TryFrom, TryInto};
8use serde::{Deserialize, Serialize};
9
10pub use self::v2::*;
16
17#[derive(Deserialize, Serialize)]
20pub enum ServerDescriptionRaw {
21 V0(v0::ServerDescription),
22 V1(v1::ServerDescription),
23 V2(ServerDescriptions),
24}
25
26impl From<ServerDescriptions> for ServerDescriptionRaw {
27 fn from(value: ServerDescriptions) -> Self {
28 Self::V2(value)
30 }
31}
32
33impl TryFrom<ServerDescriptionRaw> for (Version, ServerDescriptions) {
34 type Error = <ServerDescriptions as EditableSetting>::Error;
35
36 fn try_from(
37 value: ServerDescriptionRaw,
38 ) -> Result<Self, <ServerDescriptions as EditableSetting>::Error> {
39 use ServerDescriptionRaw::*;
40 Ok(match value {
41 V0(value) => (Version::Old, value.try_into()?),
43 V1(value) => (Version::Old, value.try_into()?),
44 V2(mut value) => (value.validate()?, value),
47 })
48 }
49}
50
51type Final = ServerDescriptions;
52
53impl EditableSetting for ServerDescriptions {
54 type Error = Infallible;
55 type Legacy = legacy::ServerDescription;
56 type Setting = ServerDescriptionRaw;
57
58 const FILENAME: &'static str = FILENAME;
59}
60
61mod legacy {
62 use super::{Final, MIGRATION_UPGRADE_GUARANTEE, v0 as next};
63 use core::convert::TryInto;
64 use serde::{Deserialize, Serialize};
65
66 #[derive(Deserialize, Serialize)]
67 #[serde(transparent)]
68 pub struct ServerDescription(pub(super) String);
69
70 impl From<ServerDescription> for Final {
71 fn from(value: ServerDescription) -> Self {
78 next::ServerDescription::migrate(value)
79 .try_into()
80 .expect(MIGRATION_UPGRADE_GUARANTEE)
81 }
82 }
83}
84
85mod v0 {
90 use super::{Final, MIGRATION_UPGRADE_GUARANTEE, legacy as prev, v1 as next};
91 use crate::settings::editable::{EditableSetting, Version};
92 use core::convert::{TryFrom, TryInto};
93 use serde::{Deserialize, Serialize};
94
95 #[derive(Clone, Deserialize, Serialize)]
96 #[serde(transparent)]
97 pub struct ServerDescription(pub(super) String);
98
99 impl ServerDescription {
100 pub(super) fn migrate(prev: prev::ServerDescription) -> Self { ServerDescription(prev.0) }
104
105 pub(super) fn validate(&mut self) -> Result<Version, <Final as EditableSetting>::Error> {
112 Ok(Version::Latest)
113 }
114 }
115
116 impl TryFrom<ServerDescription> for Final {
119 type Error = <Final as EditableSetting>::Error;
120
121 fn try_from(mut value: ServerDescription) -> Result<Final, Self::Error> {
122 value.validate()?;
123 Ok(next::ServerDescription::migrate(value)
124 .try_into()
125 .expect(MIGRATION_UPGRADE_GUARANTEE))
126 }
127 }
128}
129
130mod v1 {
131 use super::{Final, v0 as prev};
132 use crate::settings::editable::{EditableSetting, Version};
133 use core::ops::{Deref, DerefMut};
134 use serde::{Deserialize, Serialize};
135
136 #[derive(Clone, Deserialize, Serialize)]
137 #[serde(transparent)]
138 pub struct ServerDescription(pub(super) String);
139
140 impl Default for ServerDescription {
141 fn default() -> Self { Self("This is the best Veloren server".into()) }
142 }
143
144 impl Deref for ServerDescription {
145 type Target = String;
146
147 fn deref(&self) -> &Self::Target { &self.0 }
148 }
149
150 impl DerefMut for ServerDescription {
151 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
152 }
153
154 impl ServerDescription {
155 pub(super) fn migrate(prev: prev::ServerDescription) -> Self { ServerDescription(prev.0) }
159
160 pub(super) fn validate(&mut self) -> Result<Version, <Final as EditableSetting>::Error> {
167 Ok(Version::Latest)
168 }
169 }
170
171 use super::v2 as next;
172 impl TryFrom<ServerDescription> for Final {
173 type Error = <Final as EditableSetting>::Error;
174
175 fn try_from(mut value: ServerDescription) -> Result<Final, Self::Error> {
176 value.validate()?;
177 Ok(next::ServerDescriptions::migrate(value))
178 }
179 }
180}
181
182mod v2 {
183 use std::collections::HashMap;
184
185 use super::{Final, v1 as prev};
186 use crate::settings::editable::{EditableSetting, Version};
187 use serde::{Deserialize, Serialize};
188
189 #[derive(Clone, Deserialize, Serialize)]
191 pub struct ServerDescriptions {
192 pub default_locale: String,
193 pub descriptions: HashMap<String, ServerDescription>,
194 }
195
196 #[derive(Clone, Deserialize, Serialize)]
197 pub struct ServerDescription {
198 pub motd: String,
199 pub rules: Option<String>,
200 }
201
202 impl Default for ServerDescriptions {
203 fn default() -> Self {
204 Self {
205 default_locale: "en".to_string(),
206 descriptions: HashMap::from([("en".to_string(), ServerDescription::default())]),
207 }
208 }
209 }
210
211 impl Default for ServerDescription {
212 fn default() -> Self {
213 Self {
214 motd: "This is the best Veloren server".into(),
215 rules: None,
216 }
217 }
218 }
219
220 impl ServerDescriptions {
221 fn unwrap_locale_or_default<'a, 'b: 'a>(&'b self, locale: Option<&'a str>) -> &'a str {
222 locale.map_or(&self.default_locale, |locale| {
223 if self.descriptions.contains_key(locale) {
224 locale
225 } else {
226 &self.default_locale
227 }
228 })
229 }
230
231 pub fn get(&self, locale: Option<&str>) -> Option<&ServerDescription> {
232 self.descriptions.get(self.unwrap_locale_or_default(locale))
233 }
234
235 pub fn get_rules(&self, locale: Option<&str>) -> Option<&str> {
238 self.descriptions
239 .get(self.unwrap_locale_or_default(locale))
240 .and_then(|d| d.rules.as_deref())
241 .or_else(|| {
242 self.descriptions
243 .get(&self.default_locale)?
244 .rules
245 .as_deref()
246 })
247 }
248 }
249
250 impl ServerDescriptions {
251 pub(super) fn migrate(prev: prev::ServerDescription) -> Self {
255 Self {
256 default_locale: "en".to_string(),
257 descriptions: HashMap::from([("en".to_string(), ServerDescription {
258 motd: prev.0,
259 rules: None,
260 })]),
261 }
262 }
263
264 pub(super) fn validate(&mut self) -> Result<Version, <Final as EditableSetting>::Error> {
271 if self.descriptions.is_empty() {
272 *self = Self::default();
273 Ok(Version::Old)
274 } else if !self.descriptions.contains_key(&self.default_locale) {
275 self.default_locale = self
278 .descriptions
279 .keys()
280 .next()
281 .expect("We know descriptions isn't empty")
282 .to_string();
283 Ok(Version::Old)
284 } else {
285 Ok(Version::Latest)
286 }
287 }
288 }
289
290 }