1
//! Program configurations.
2

            
3
use std::{collections::HashMap, env};
4

            
5
use clap::{
6
    builder::{BoolValueParser, RangedU64ValueParser},
7
    Arg, ArgMatches, Command,
8
};
9
use serde::Deserialize;
10

            
11
use sylvia_iot_corelib::constants::{CacheEngine, DbEngine};
12

            
13
/// Configuration file object.
14
#[derive(Default, Deserialize)]
15
pub struct Config {
16
    /// **sylvia-iot-auth** API base path with host. For example: `http://localhost:1080/auth`.
17
    pub auth: Option<String>,
18
    pub db: Option<Db>,
19
    pub cache: Option<Cache>,
20
    pub mq: Option<Mq>,
21
    #[serde(rename = "mqChannels")]
22
    pub mq_channels: Option<MqChannels>,
23
    #[serde(rename = "apiScopes")]
24
    pub api_scopes: Option<HashMap<String, Vec<String>>>,
25
}
26

            
27
/// Database configuration object.
28
#[derive(Default, Deserialize)]
29
pub struct Db {
30
    /// Select the model implementation.
31
    /// - `mongodb`: pure MongoDB.
32
    /// - `sqlite`: pure SQLite.
33
    pub engine: Option<String>,
34
    pub mongodb: Option<MongoDb>,
35
    pub sqlite: Option<Sqlite>,
36
}
37

            
38
/// MongoDB configuration object.
39
#[derive(Default, Deserialize)]
40
pub struct MongoDb {
41
    /// Use `mongodb://username:password@host:port` format.
42
    pub url: Option<String>,
43
    pub database: Option<String>,
44
    #[serde(rename = "poolSize")]
45
    pub pool_size: Option<u32>,
46
}
47

            
48
/// SQLite configuration object.
49
#[derive(Default, Deserialize)]
50
pub struct Sqlite {
51
    /// Use absolute/relative path.
52
    pub path: Option<String>,
53
}
54

            
55
/// Cache configuration object.
56
#[derive(Default, Deserialize)]
57
pub struct Cache {
58
    /// Select the cache implementation.
59
    /// - `none`: disable cache.
60
    /// - `memory`: pure memory.
61
    pub engine: Option<String>,
62
    pub memory: Option<MemoryCache>,
63
}
64

            
65
/// Memory cache configuration object.
66
#[derive(Default, Deserialize)]
67
pub struct MemoryCache {
68
    /// Maximum number of device cache count.
69
    pub device: Option<usize>,
70
    /// Maximum number of device route cache count.
71
    #[serde(rename = "deviceRoute")]
72
    pub device_route: Option<usize>,
73
    /// Maximum number of network route cache count.
74
    #[serde(rename = "networkRoute")]
75
    pub network_route: Option<usize>,
76
}
77

            
78
/// Message queue configuration object.
79
#[derive(Default, Deserialize)]
80
pub struct Mq {
81
    /// AMQP QoS prefetch from **1** to **65535**. None or zero use default value **100**.
82
    pub prefetch: Option<u16>,
83
    /// AMQP persistent.
84
    pub persistent: Option<bool>,
85
    /// MQTT shared subscription topic prefix.
86
    #[serde(rename = "sharedPrefix")]
87
    pub shared_prefix: Option<String>,
88
}
89

            
90
/// Message channels configuration object.
91
#[derive(Default, Deserialize)]
92
pub struct MqChannels {
93
    pub unit: Option<BrokerCtrl>,
94
    pub application: Option<BrokerCtrl>,
95
    pub network: Option<BrokerCtrl>,
96
    pub device: Option<BrokerCtrl>,
97
    #[serde(rename = "deviceRoute")]
98
    pub device_route: Option<BrokerCtrl>,
99
    #[serde(rename = "networkRoute")]
100
    pub network_route: Option<BrokerCtrl>,
101
    pub data: Option<BrokerData>,
102
}
103

            
104
/// Channel `broker.ctrl` configuration object.
105
#[derive(Default, Deserialize)]
106
pub struct BrokerCtrl {
107
    /// Queue connection URL of the control channel.
108
    pub url: Option<String>,
109
    /// AMQP QoS prefetch from **1** to **65535**. None or zero use default value **100**.
110
    pub prefetch: Option<u16>,
111
}
112

            
113
/// Channel `broker.data` configuration object.
114
#[derive(Default, Deserialize)]
115
pub struct BrokerData {
116
    /// Queue connection URL of the data channel.
117
    pub url: Option<String>,
118
    /// AMQP persistent.
119
    pub persistent: Option<bool>,
120
}
121

            
122
pub const DEF_AUTH: &'static str = "http://localhost:1080/auth";
123
pub const DEF_ENGINE: &'static str = DbEngine::SQLITE;
124
pub const DEF_MONGODB_URL: &'static str = "mongodb://localhost:27017";
125
pub const DEF_MONGODB_DB: &'static str = "broker";
126
pub const DEF_SQLITE_PATH: &'static str = "broker.db";
127
pub const DEF_CACHE_ENGINE: &'static str = CacheEngine::NONE;
128
pub const DEF_MEMORY_DEVICE: usize = 1_000_000;
129
pub const DEF_MEMORY_DEVICE_ROUTE: usize = 1_000_000;
130
pub const DEF_MEMORY_NETWORK_ROUTE: usize = 1_000_000;
131
pub const DEF_MQ_PREFETCH: u16 = 100;
132
pub const DEF_MQ_PERSISTENT: bool = false;
133
pub const DEF_MQ_SHAREDPREFIX: &'static str = "$share/sylvia-iot-broker/";
134
pub const DEF_MQ_CHANNEL_URL: &'static str = "amqp://localhost";
135

            
136
/// To register Clap arguments.
137
8
pub fn reg_args(cmd: Command) -> Command {
138
8
    cmd.arg(
139
8
        Arg::new("broker.auth")
140
8
            .long("broker.auth")
141
8
            .help("sylvia-iot-auth host (ex: http://localhost:1080/auth)")
142
8
            .num_args(1),
143
8
    )
144
8
    .arg(
145
8
        Arg::new("broker.db.engine")
146
8
            .long("broker.db.engine")
147
8
            .help("database engine")
148
8
            .num_args(1)
149
8
            .value_parser([DbEngine::MONGODB, DbEngine::SQLITE]),
150
8
    )
151
8
    .arg(
152
8
        Arg::new("broker.db.mongodb.url")
153
8
            .long("broker.db.mongodb.url")
154
8
            .help("MongoDB URL (scheme://[username][:password][@][host][:port]")
155
8
            .num_args(1),
156
8
    )
157
8
    .arg(
158
8
        Arg::new("broker.db.mongodb.database")
159
8
            .long("broker.db.mongodb.database")
160
8
            .help("database nane")
161
8
            .num_args(1),
162
8
    )
163
8
    .arg(
164
8
        Arg::new("broker.db.mongodb.poolsize")
165
8
            .long("broker.db.mongodb.poolsize")
166
8
            .help("connection pool size")
167
8
            .num_args(1)
168
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u32::MAX as u64)),
169
8
    )
170
8
    .arg(
171
8
        Arg::new("broker.db.sqlite.path")
172
8
            .long("broker.db.sqlite.path")
173
8
            .help("SQLite path")
174
8
            .num_args(1),
175
8
    )
176
8
    .arg(
177
8
        Arg::new("broker.cache.engine")
178
8
            .long("broker.cache.engine")
179
8
            .help("cache engine")
180
8
            .num_args(1)
181
8
            .value_parser([CacheEngine::MEMORY, CacheEngine::NONE]),
182
8
    )
183
8
    .arg(
184
8
        Arg::new("broker.cache.memory.device")
185
8
            .long("broker.cache.memory.device")
186
8
            .help("Device cache size")
187
8
            .num_args(1)
188
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
189
8
    )
190
8
    .arg(
191
8
        Arg::new("broker.cache.memory.device-route")
192
8
            .long("broker.cache.memory.device-route")
193
8
            .help("Device route cache size")
194
8
            .num_args(1)
195
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
196
8
    )
197
8
    .arg(
198
8
        Arg::new("broker.cache.memory.network-route")
199
8
            .long("broker.cache.memory.network-route")
200
8
            .help("Network route cache size")
201
8
            .num_args(1)
202
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
203
8
    )
204
8
    .arg(
205
8
        Arg::new("broker.mq.prefetch")
206
8
            .long("broker.mq.prefetch")
207
8
            .help("AMQP prefetch")
208
8
            .num_args(1)
209
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
210
8
    )
211
8
    .arg(
212
8
        Arg::new("broker.mq.persistent")
213
8
            .long("broker.mq.persistent")
214
8
            .help("AMQP persistent")
215
8
            .num_args(1)
216
8
            .value_parser(BoolValueParser::new()),
217
8
    )
218
8
    .arg(
219
8
        Arg::new("broker.mq.sharedprefix")
220
8
            .long("broker.mq.sharedprefix")
221
8
            .help("MQTT shared subscription prefix")
222
8
            .num_args(1),
223
8
    )
224
8
    .arg(
225
8
        Arg::new("broker.mq-channels.unit.url")
226
8
            .long("broker.mq-channels.unit.url")
227
8
            .help("URL of `broker.ctrl.unit` channel")
228
8
            .num_args(1),
229
8
    )
230
8
    .arg(
231
8
        Arg::new("broker.mq-channels.unit.prefetch")
232
8
            .long("broker.mq-channels.unit.prefetch")
233
8
            .help("AMQP prefetch for `broker.ctrl.unit` channel")
234
8
            .num_args(1)
235
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
236
8
    )
237
8
    .arg(
238
8
        Arg::new("broker.mq-channels.application.url")
239
8
            .long("broker.mq-channels.application.url")
240
8
            .help("URL of `broker.ctrl.application` channel")
241
8
            .num_args(1),
242
8
    )
243
8
    .arg(
244
8
        Arg::new("broker.mq-channels.application.prefetch")
245
8
            .long("broker.mq-channels.application.prefetch")
246
8
            .help("AMQP prefetch for `broker.ctrl.application` channel")
247
8
            .num_args(1)
248
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
249
8
    )
250
8
    .arg(
251
8
        Arg::new("broker.mq-channels.network.url")
252
8
            .long("broker.mq-channels.network.url")
253
8
            .help("URL of `broker.ctrl.network` channel")
254
8
            .num_args(1),
255
8
    )
256
8
    .arg(
257
8
        Arg::new("broker.mq-channels.network.prefetch")
258
8
            .long("broker.mq-channels.network.prefetch")
259
8
            .help("AMQP prefetch for `broker.ctrl.network` channel")
260
8
            .num_args(1)
261
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
262
8
    )
263
8
    .arg(
264
8
        Arg::new("broker.mq-channels.device.url")
265
8
            .long("broker.mq-channels.device.url")
266
8
            .help("URL of `broker.ctrl.device` channel")
267
8
            .num_args(1),
268
8
    )
269
8
    .arg(
270
8
        Arg::new("broker.mq-channels.device.prefetch")
271
8
            .long("broker.mq-channels.device.prefetch")
272
8
            .help("AMQP prefetch for `broker.ctrl.device` channel")
273
8
            .num_args(1)
274
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
275
8
    )
276
8
    .arg(
277
8
        Arg::new("broker.mq-channels.device-route.url")
278
8
            .long("broker.mq-channels.device-route.url")
279
8
            .help("URL of `broker.ctrl.device-route` channel")
280
8
            .num_args(1),
281
8
    )
282
8
    .arg(
283
8
        Arg::new("broker.mq-channels.device-route.prefetch")
284
8
            .long("broker.mq-channels.device-route.prefetch")
285
8
            .help("AMQP prefetch for `broker.ctrl.device-route` channel")
286
8
            .num_args(1)
287
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
288
8
    )
289
8
    .arg(
290
8
        Arg::new("broker.mq-channels.network-route.url")
291
8
            .long("broker.mq-channels.network-route.url")
292
8
            .help("URL of `broker.ctrl.network-route` channel")
293
8
            .num_args(1),
294
8
    )
295
8
    .arg(
296
8
        Arg::new("broker.mq-channels.network-route.prefetch")
297
8
            .long("broker.mq-channels.network-route.prefetch")
298
8
            .help("AMQP prefetch for `broker.ctrl.network-route` channel")
299
8
            .num_args(1)
300
8
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
301
8
    )
302
8
    .arg(
303
8
        Arg::new("broker.mq-channels.data.url")
304
8
            .long("broker.mq-channels.data.url")
305
8
            .help("URL of `broker.data` channel")
306
8
            .num_args(1),
307
8
    )
308
8
    .arg(
309
8
        Arg::new("broker.mq-channels.data.persistent")
310
8
            .long("broker.mq-channels.data.persistent")
311
8
            .help("AMQP persistent for `broker.data` channel")
312
8
            .num_args(1)
313
8
            .value_parser(BoolValueParser::new()),
314
8
    )
315
8
    .arg(
316
8
        Arg::new("broker.api-scopes")
317
8
            .long("broker.api-scopes")
318
8
            .help("API scopes")
319
8
            .num_args(0..),
320
8
    )
321
8
}
322

            
323
/// To read input arguments from command-line arguments and environment variables.
324
///
325
/// This function will call [`apply_default()`] to fill missing values so you do not need call it
326
/// again.
327
8
pub fn read_args(args: &ArgMatches) -> Config {
328
8
    apply_default(&Config {
329
8
        auth: match args.get_one::<String>("broker.auth") {
330
6
            None => match env::var("BROKER_AUTH") {
331
3
                Err(_) => None,
332
3
                Ok(v) => Some(v),
333
            },
334
2
            Some(v) => Some(v.clone()),
335
        },
336
        db: Some(Db {
337
8
            engine: match args.get_one::<String>("broker.db.engine") {
338
5
                None => match env::var("BROKER_DB_ENGINE") {
339
2
                    Err(_) => None,
340
3
                    Ok(v) => Some(v),
341
                },
342
3
                Some(v) => Some(v.clone()),
343
            },
344
            mongodb: Some(MongoDb {
345
8
                url: match args.get_one::<String>("broker.db.mongodb.url") {
346
6
                    None => match env::var("BROKER_DB_MONGODB_URL") {
347
3
                        Err(_) => None,
348
3
                        Ok(v) => Some(v),
349
                    },
350
2
                    Some(v) => Some(v.clone()),
351
                },
352
8
                database: match args.get_one::<String>("broker.db.mongodb.database") {
353
6
                    None => match env::var("BROKER_DB_MONGODB_DATABASE") {
354
3
                        Err(_) => None,
355
3
                        Ok(v) => Some(v),
356
                    },
357
2
                    Some(v) => Some(v.clone()),
358
                },
359
8
                pool_size: match args.get_one::<u64>("broker.db.mongodb.poolsize") {
360
6
                    None => match env::var("BROKER_DB_MONGODB_POOLSIZE") {
361
3
                        Err(_) => None,
362
3
                        Ok(v) => match v.parse::<u32>() {
363
1
                            Err(_) => None,
364
2
                            Ok(v) => Some(v),
365
                        },
366
                    },
367
2
                    Some(v) => Some(*v as u32),
368
                },
369
            }),
370
            sqlite: Some(Sqlite {
371
8
                path: match args.get_one::<String>("broker.db.sqlite.path") {
372
6
                    None => match env::var("BROKER_DB_SQLITE_PATH") {
373
3
                        Err(_) => None,
374
3
                        Ok(v) => Some(v),
375
                    },
376
2
                    Some(v) => Some(v.clone()),
377
                },
378
            }),
379
        }),
380
        cache: Some(Cache {
381
8
            engine: match args.get_one::<String>("broker.cache.engine") {
382
5
                None => match env::var("BROKER_CACHE_ENGINE") {
383
2
                    Err(_) => None,
384
3
                    Ok(v) => Some(v),
385
                },
386
3
                Some(v) => Some(v.clone()),
387
            },
388
            memory: Some(MemoryCache {
389
8
                device: match args.get_one::<u64>("broker.cache.memory.device") {
390
6
                    None => match env::var("BROKER_CACHE_MEMORY_DEVICE") {
391
3
                        Err(_) => None,
392
3
                        Ok(v) => match v.parse::<usize>() {
393
1
                            Err(_) => None,
394
2
                            Ok(v) => Some(v),
395
                        },
396
                    },
397
2
                    Some(v) => Some(*v as usize),
398
                },
399
8
                device_route: match args.get_one::<u64>("broker.cache.memory.device-route") {
400
6
                    None => match env::var("BROKER_CACHE_MEMORY_DEVICE_ROUTE") {
401
3
                        Err(_) => None,
402
3
                        Ok(v) => match v.parse::<usize>() {
403
1
                            Err(_) => None,
404
2
                            Ok(v) => Some(v),
405
                        },
406
                    },
407
2
                    Some(v) => Some(*v as usize),
408
                },
409
8
                network_route: match args.get_one::<u64>("broker.cache.memory.network-route") {
410
6
                    None => match env::var("BROKER_CACHE_MEMORY_NETWORK_ROUTE") {
411
3
                        Err(_) => None,
412
3
                        Ok(v) => match v.parse::<usize>() {
413
1
                            Err(_) => None,
414
2
                            Ok(v) => Some(v),
415
                        },
416
                    },
417
2
                    Some(v) => Some(*v as usize),
418
                },
419
            }),
420
        }),
421
        mq: Some(Mq {
422
8
            prefetch: match args.get_one::<u64>("broker.mq.prefetch") {
423
6
                None => match env::var("BROKER_MQ_PREFETCH") {
424
3
                    Err(_) => None,
425
3
                    Ok(v) => match v.parse::<u16>() {
426
1
                        Err(_) => None,
427
2
                        Ok(v) => Some(v),
428
                    },
429
                },
430
2
                Some(v) => Some(*v as u16),
431
            },
432
8
            persistent: match args.get_one::<bool>("broker.mq.persistent") {
433
6
                None => match env::var("BROKER_MQ_PERSISTENT") {
434
3
                    Err(_) => None,
435
3
                    Ok(v) => match v.parse::<bool>() {
436
1
                        Err(_) => None,
437
2
                        Ok(v) => Some(v),
438
                    },
439
                },
440
2
                Some(v) => Some(*v as bool),
441
            },
442
8
            shared_prefix: match args.get_one::<String>("broker.mq.sharedprefix") {
443
5
                None => match env::var("BROKER_MQ_SHAREDPREFIX") {
444
2
                    Err(_) => None,
445
3
                    Ok(v) => Some(v),
446
                },
447
3
                Some(v) => Some(v.clone()),
448
            },
449
        }),
450
        mq_channels: Some(MqChannels {
451
            unit: Some(BrokerCtrl {
452
8
                url: match args.get_one::<String>("broker.mq-channels.unit.url") {
453
6
                    None => match env::var("BROKER_MQCHANNELS_UNIT_URL") {
454
3
                        Err(_) => None,
455
3
                        Ok(v) => Some(v),
456
                    },
457
2
                    Some(v) => Some(v.clone()),
458
                },
459
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.unit.prefetch") {
460
6
                    None => match env::var("BROKER_MQCHANNELS_UNIT_PREFETCH") {
461
3
                        Err(_) => None,
462
3
                        Ok(v) => match v.parse::<u16>() {
463
1
                            Err(_) => None,
464
2
                            Ok(v) => Some(v),
465
                        },
466
                    },
467
2
                    Some(v) => Some(*v as u16),
468
                },
469
            }),
470
            application: Some(BrokerCtrl {
471
8
                url: match args.get_one::<String>("broker.mq-channels.application.url") {
472
6
                    None => match env::var("BROKER_MQCHANNELS_APPLICATION_URL") {
473
3
                        Err(_) => None,
474
3
                        Ok(v) => Some(v),
475
                    },
476
2
                    Some(v) => Some(v.clone()),
477
                },
478
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.application.prefetch") {
479
6
                    None => match env::var("BROKER_MQCHANNELS_APPLICATION_PREFETCH") {
480
3
                        Err(_) => None,
481
3
                        Ok(v) => match v.parse::<u16>() {
482
1
                            Err(_) => None,
483
2
                            Ok(v) => Some(v),
484
                        },
485
                    },
486
2
                    Some(v) => Some(*v as u16),
487
                },
488
            }),
489
            network: Some(BrokerCtrl {
490
8
                url: match args.get_one::<String>("broker.mq-channels.network.url") {
491
6
                    None => match env::var("BROKER_MQCHANNELS_NETWORK_URL") {
492
3
                        Err(_) => None,
493
3
                        Ok(v) => Some(v),
494
                    },
495
2
                    Some(v) => Some(v.clone()),
496
                },
497
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.network.prefetch") {
498
6
                    None => match env::var("BROKER_MQCHANNELS_NETWORK_PREFETCH") {
499
3
                        Err(_) => None,
500
3
                        Ok(v) => match v.parse::<u16>() {
501
1
                            Err(_) => None,
502
2
                            Ok(v) => Some(v),
503
                        },
504
                    },
505
2
                    Some(v) => Some(*v as u16),
506
                },
507
            }),
508
            device: Some(BrokerCtrl {
509
8
                url: match args.get_one::<String>("broker.mq-channels.device.url") {
510
6
                    None => match env::var("BROKER_MQCHANNELS_DEVICE_URL") {
511
3
                        Err(_) => None,
512
3
                        Ok(v) => Some(v),
513
                    },
514
2
                    Some(v) => Some(v.clone()),
515
                },
516
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.device.prefetch") {
517
6
                    None => match env::var("BROKER_MQCHANNELS_DEVICE_PREFETCH") {
518
3
                        Err(_) => None,
519
3
                        Ok(v) => match v.parse::<u16>() {
520
1
                            Err(_) => None,
521
2
                            Ok(v) => Some(v),
522
                        },
523
                    },
524
2
                    Some(v) => Some(*v as u16),
525
                },
526
            }),
527
            device_route: Some(BrokerCtrl {
528
8
                url: match args.get_one::<String>("broker.mq-channels.device-route.url") {
529
6
                    None => match env::var("BROKER_MQCHANNELS_DEVICE_ROUTE_URL") {
530
3
                        Err(_) => None,
531
3
                        Ok(v) => Some(v),
532
                    },
533
2
                    Some(v) => Some(v.clone()),
534
                },
535
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.device-route.prefetch") {
536
6
                    None => match env::var("BROKER_MQCHANNELS_DEVICE_ROUTE_PREFETCH") {
537
3
                        Err(_) => None,
538
3
                        Ok(v) => match v.parse::<u16>() {
539
1
                            Err(_) => None,
540
2
                            Ok(v) => Some(v),
541
                        },
542
                    },
543
2
                    Some(v) => Some(*v as u16),
544
                },
545
            }),
546
            network_route: Some(BrokerCtrl {
547
8
                url: match args.get_one::<String>("broker.mq-channels.network-route.url") {
548
6
                    None => match env::var("BROKER_MQCHANNELS_NETWORK_ROUTE_URL") {
549
3
                        Err(_) => None,
550
3
                        Ok(v) => Some(v),
551
                    },
552
2
                    Some(v) => Some(v.clone()),
553
                },
554
8
                prefetch: match args.get_one::<u64>("broker.mq-channels.network-route.prefetch") {
555
6
                    None => match env::var("BROKER_MQCHANNELS_NETWORK_ROUTE_PREFETCH") {
556
3
                        Err(_) => None,
557
3
                        Ok(v) => match v.parse::<u16>() {
558
1
                            Err(_) => None,
559
2
                            Ok(v) => Some(v),
560
                        },
561
                    },
562
2
                    Some(v) => Some(*v as u16),
563
                },
564
            }),
565
            data: Some(BrokerData {
566
8
                url: match args.get_one::<String>("broker.mq-channels.data.url") {
567
6
                    None => match env::var("BROKER_MQCHANNELS_DATA_URL") {
568
3
                        Err(_) => None,
569
3
                        Ok(v) => Some(v),
570
                    },
571
2
                    Some(v) => Some(v.clone()),
572
                },
573
8
                persistent: match args.get_one::<bool>("broker.mq-channels.data.persistent") {
574
5
                    None => match env::var("BROKER_MQCHANNELS_DATA_PERSISTENT") {
575
2
                        Err(_) => None,
576
3
                        Ok(v) => match v.parse::<bool>() {
577
1
                            Err(_) => None,
578
2
                            Ok(v) => Some(v),
579
                        },
580
                    },
581
3
                    Some(v) => Some(*v as bool),
582
                },
583
            }),
584
        }),
585
8
        api_scopes: match args.get_one::<String>("broker.api-scopes") {
586
4
            None => match env::var("BROKER_API_SCOPES") {
587
1
                Err(_) => None,
588
3
                Ok(v) => match v.len() {
589
1
                    0 => None,
590
2
                    _ => match serde_json::from_str::<HashMap<String, Vec<String>>>(v.as_str()) {
591
1
                        Err(_) => None,
592
1
                        Ok(v) => Some(v),
593
                    },
594
                },
595
            },
596
4
            Some(v) => match v.len() {
597
1
                0 => None,
598
3
                _ => match serde_json::from_str::<HashMap<String, Vec<String>>>(v.as_str()) {
599
1
                    Err(_) => None,
600
2
                    Ok(v) => Some(v),
601
                },
602
            },
603
        },
604
    })
605
8
}
606

            
607
/// Fill missing configuration with default values.
608
27
pub fn apply_default(config: &Config) -> Config {
609
27
    Config {
610
27
        auth: match config.auth.as_ref() {
611
9
            None => Some(DEF_AUTH.to_string()),
612
18
            Some(auth) => Some(auth.clone()),
613
        },
614
27
        db: match config.db.as_ref() {
615
2
            None => Some(Db {
616
2
                engine: Some(DEF_ENGINE.to_string()),
617
2
                mongodb: Some(MongoDb {
618
2
                    url: Some(DEF_MONGODB_URL.to_string()),
619
2
                    database: Some(DEF_MONGODB_DB.to_string()),
620
2
                    pool_size: None,
621
2
                }),
622
2
                sqlite: Some(Sqlite {
623
2
                    path: Some(DEF_SQLITE_PATH.to_string()),
624
2
                }),
625
2
            }),
626
25
            Some(db) => Some(Db {
627
25
                engine: match db.engine.as_ref() {
628
3
                    None => Some(DEF_ENGINE.to_string()),
629
22
                    Some(engine) => match engine.as_str() {
630
22
                        DbEngine::MONGODB => Some(DbEngine::MONGODB.to_string()),
631
13
                        DbEngine::SQLITE => Some(DbEngine::SQLITE.to_string()),
632
3
                        _ => Some(DEF_ENGINE.to_string()),
633
                    },
634
                },
635
25
                mongodb: match db.mongodb.as_ref() {
636
4
                    None => Some(MongoDb {
637
4
                        url: Some(DEF_MONGODB_URL.to_string()),
638
4
                        database: Some(DEF_MONGODB_DB.to_string()),
639
4
                        pool_size: None,
640
4
                    }),
641
21
                    Some(mongodb) => Some(MongoDb {
642
21
                        url: match mongodb.url.as_ref() {
643
3
                            None => Some(DEF_MONGODB_URL.to_string()),
644
18
                            Some(url) => Some(url.to_string()),
645
                        },
646
21
                        database: match mongodb.database.as_ref() {
647
3
                            None => Some(DEF_MONGODB_DB.to_string()),
648
18
                            Some(database) => Some(database.to_string()),
649
                        },
650
21
                        pool_size: mongodb.pool_size,
651
                    }),
652
                },
653
25
                sqlite: match db.sqlite.as_ref() {
654
4
                    None => Some(Sqlite {
655
4
                        path: Some(DEF_SQLITE_PATH.to_string()),
656
4
                    }),
657
21
                    Some(sqlite) => Some(Sqlite {
658
21
                        path: match sqlite.path.as_ref() {
659
3
                            None => Some(DEF_SQLITE_PATH.to_string()),
660
18
                            Some(path) => Some(path.to_string()),
661
                        },
662
                    }),
663
                },
664
            }),
665
        },
666
27
        cache: match config.cache.as_ref() {
667
7
            None => Some(Cache {
668
7
                engine: Some(DEF_CACHE_ENGINE.to_string()),
669
7
                memory: Some(MemoryCache {
670
7
                    device: Some(DEF_MEMORY_DEVICE),
671
7
                    device_route: Some(DEF_MEMORY_DEVICE_ROUTE),
672
7
                    network_route: Some(DEF_MEMORY_NETWORK_ROUTE),
673
7
                }),
674
7
            }),
675
20
            Some(cache) => Some(Cache {
676
20
                engine: match cache.engine.as_ref() {
677
3
                    None => Some(DEF_CACHE_ENGINE.to_string()),
678
17
                    Some(engine) => match engine.as_str() {
679
17
                        CacheEngine::MEMORY => Some(CacheEngine::MEMORY.to_string()),
680
10
                        _ => Some(DEF_CACHE_ENGINE.to_string()),
681
                    },
682
                },
683
20
                memory: match cache.memory.as_ref() {
684
11
                    None => Some(MemoryCache {
685
11
                        device: Some(DEF_MEMORY_DEVICE),
686
11
                        device_route: Some(DEF_MEMORY_DEVICE_ROUTE),
687
11
                        network_route: Some(DEF_MEMORY_NETWORK_ROUTE),
688
11
                    }),
689
9
                    Some(memory) => Some(MemoryCache {
690
9
                        device: match memory.device {
691
4
                            None | Some(0) => Some(DEF_MEMORY_DEVICE),
692
5
                            Some(v) => Some(v),
693
                        },
694
9
                        device_route: match memory.device_route {
695
4
                            None | Some(0) => Some(DEF_MEMORY_DEVICE_ROUTE),
696
5
                            Some(v) => Some(v),
697
                        },
698
9
                        network_route: match memory.network_route {
699
4
                            None | Some(0) => Some(DEF_MEMORY_NETWORK_ROUTE),
700
5
                            Some(v) => Some(v),
701
                        },
702
                    }),
703
                },
704
            }),
705
        },
706
27
        mq: match config.mq.as_ref() {
707
16
            None => Some(Mq {
708
16
                prefetch: Some(DEF_MQ_PREFETCH),
709
16
                persistent: Some(DEF_MQ_PERSISTENT),
710
16
                shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
711
16
            }),
712
11
            Some(mq) => Some(Mq {
713
11
                prefetch: match mq.prefetch {
714
6
                    None | Some(0) => Some(DEF_MQ_PREFETCH),
715
5
                    Some(prefetch) => Some(prefetch),
716
                },
717
11
                persistent: match mq.persistent {
718
6
                    None => Some(DEF_MQ_PERSISTENT),
719
5
                    Some(persistent) => Some(persistent),
720
                },
721
11
                shared_prefix: match mq.shared_prefix.as_ref() {
722
4
                    None => Some(DEF_MQ_SHAREDPREFIX.to_string()),
723
7
                    Some(shared_prefix) => Some(shared_prefix.to_string()),
724
                },
725
            }),
726
        },
727
27
        mq_channels: match config.mq_channels.as_ref() {
728
8
            None => Some(MqChannels {
729
8
                unit: Some(BrokerCtrl {
730
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
731
8
                    prefetch: Some(DEF_MQ_PREFETCH),
732
8
                }),
733
8
                application: Some(BrokerCtrl {
734
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
735
8
                    prefetch: Some(DEF_MQ_PREFETCH),
736
8
                }),
737
8
                network: Some(BrokerCtrl {
738
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
739
8
                    prefetch: Some(DEF_MQ_PREFETCH),
740
8
                }),
741
8
                device: Some(BrokerCtrl {
742
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
743
8
                    prefetch: Some(DEF_MQ_PREFETCH),
744
8
                }),
745
8
                device_route: Some(BrokerCtrl {
746
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
747
8
                    prefetch: Some(DEF_MQ_PREFETCH),
748
8
                }),
749
8
                network_route: Some(BrokerCtrl {
750
8
                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
751
8
                    prefetch: Some(DEF_MQ_PREFETCH),
752
8
                }),
753
8
                data: None,
754
8
            }),
755
19
            Some(mq_channels) => Some(MqChannels {
756
19
                unit: match mq_channels.unit.as_ref() {
757
9
                    None => Some(BrokerCtrl {
758
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
759
9
                        prefetch: Some(DEF_MQ_PREFETCH),
760
9
                    }),
761
10
                    Some(channel) => Some(BrokerCtrl {
762
10
                        url: match channel.url.as_ref() {
763
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
764
6
                            Some(url) => Some(url.to_string()),
765
                        },
766
10
                        prefetch: match channel.prefetch {
767
5
                            None => Some(DEF_MQ_PREFETCH),
768
5
                            Some(prefetch) => Some(prefetch),
769
                        },
770
                    }),
771
                },
772
19
                application: match mq_channels.application.as_ref() {
773
9
                    None => Some(BrokerCtrl {
774
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
775
9
                        prefetch: Some(DEF_MQ_PREFETCH),
776
9
                    }),
777
10
                    Some(channel) => Some(BrokerCtrl {
778
10
                        url: match channel.url.as_ref() {
779
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
780
6
                            Some(url) => Some(url.to_string()),
781
                        },
782
10
                        prefetch: match channel.prefetch {
783
5
                            None => Some(DEF_MQ_PREFETCH),
784
5
                            Some(prefetch) => Some(prefetch),
785
                        },
786
                    }),
787
                },
788
19
                network: match mq_channels.network.as_ref() {
789
9
                    None => Some(BrokerCtrl {
790
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
791
9
                        prefetch: Some(DEF_MQ_PREFETCH),
792
9
                    }),
793
10
                    Some(channel) => Some(BrokerCtrl {
794
10
                        url: match channel.url.as_ref() {
795
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
796
6
                            Some(url) => Some(url.to_string()),
797
                        },
798
10
                        prefetch: match channel.prefetch {
799
5
                            None => Some(DEF_MQ_PREFETCH),
800
5
                            Some(prefetch) => Some(prefetch),
801
                        },
802
                    }),
803
                },
804
19
                device: match mq_channels.device.as_ref() {
805
9
                    None => Some(BrokerCtrl {
806
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
807
9
                        prefetch: Some(DEF_MQ_PREFETCH),
808
9
                    }),
809
10
                    Some(channel) => Some(BrokerCtrl {
810
10
                        url: match channel.url.as_ref() {
811
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
812
6
                            Some(url) => Some(url.to_string()),
813
                        },
814
10
                        prefetch: match channel.prefetch {
815
5
                            None => Some(DEF_MQ_PREFETCH),
816
5
                            Some(prefetch) => Some(prefetch),
817
                        },
818
                    }),
819
                },
820
19
                device_route: match mq_channels.device_route.as_ref() {
821
9
                    None => Some(BrokerCtrl {
822
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
823
9
                        prefetch: Some(DEF_MQ_PREFETCH),
824
9
                    }),
825
10
                    Some(channel) => Some(BrokerCtrl {
826
10
                        url: match channel.url.as_ref() {
827
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
828
6
                            Some(url) => Some(url.to_string()),
829
                        },
830
10
                        prefetch: match channel.prefetch {
831
5
                            None => Some(DEF_MQ_PREFETCH),
832
5
                            Some(prefetch) => Some(prefetch),
833
                        },
834
                    }),
835
                },
836
19
                network_route: match mq_channels.network_route.as_ref() {
837
9
                    None => Some(BrokerCtrl {
838
9
                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
839
9
                        prefetch: Some(DEF_MQ_PREFETCH),
840
9
                    }),
841
10
                    Some(channel) => Some(BrokerCtrl {
842
10
                        url: match channel.url.as_ref() {
843
4
                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
844
6
                            Some(url) => Some(url.to_string()),
845
                        },
846
10
                        prefetch: match channel.prefetch {
847
5
                            None => Some(DEF_MQ_PREFETCH),
848
5
                            Some(prefetch) => Some(prefetch),
849
                        },
850
                    }),
851
                },
852
19
                data: match mq_channels.data.as_ref() {
853
1
                    None => None,
854
18
                    Some(channel) => Some(BrokerData {
855
18
                        url: match channel.url.as_ref() {
856
4
                            None => None,
857
14
                            Some(url) => Some(url.to_string()),
858
                        },
859
18
                        persistent: match channel.persistent {
860
12
                            None => Some(DEF_MQ_PERSISTENT),
861
6
                            Some(persistent) => Some(persistent),
862
                        },
863
                    }),
864
                },
865
            }),
866
        },
867
27
        api_scopes: match config.api_scopes.as_ref() {
868
23
            None => Some(HashMap::new()),
869
4
            Some(scopes) => Some(scopes.clone()),
870
        },
871
    }
872
27
}