sylvia_iot_broker/libs/
config.rs

1//! Program configurations.
2
3use std::{collections::HashMap, env};
4
5use clap::{
6    builder::{BoolValueParser, RangedU64ValueParser},
7    Arg, ArgMatches, Command,
8};
9use serde::Deserialize;
10
11use sylvia_iot_corelib::constants::{CacheEngine, DbEngine};
12
13/// Configuration file object.
14#[derive(Default, Deserialize)]
15pub 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)]
29pub 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)]
40pub 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)]
50pub struct Sqlite {
51    /// Use absolute/relative path.
52    pub path: Option<String>,
53}
54
55/// Cache configuration object.
56#[derive(Default, Deserialize)]
57pub 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)]
67pub 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)]
80pub 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)]
92pub 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)]
106pub 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)]
115pub 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
122pub const DEF_AUTH: &'static str = "http://localhost:1080/auth";
123pub const DEF_ENGINE: &'static str = DbEngine::SQLITE;
124pub const DEF_MONGODB_URL: &'static str = "mongodb://localhost:27017";
125pub const DEF_MONGODB_DB: &'static str = "broker";
126pub const DEF_SQLITE_PATH: &'static str = "broker.db";
127pub const DEF_CACHE_ENGINE: &'static str = CacheEngine::NONE;
128pub const DEF_MEMORY_DEVICE: usize = 1_000_000;
129pub const DEF_MEMORY_DEVICE_ROUTE: usize = 1_000_000;
130pub const DEF_MEMORY_NETWORK_ROUTE: usize = 1_000_000;
131pub const DEF_MQ_PREFETCH: u16 = 100;
132pub const DEF_MQ_PERSISTENT: bool = false;
133pub const DEF_MQ_SHAREDPREFIX: &'static str = "$share/sylvia-iot-broker/";
134pub const DEF_MQ_CHANNEL_URL: &'static str = "amqp://localhost";
135
136/// To register Clap arguments.
137pub fn reg_args(cmd: Command) -> Command {
138    cmd.arg(
139        Arg::new("broker.auth")
140            .long("broker.auth")
141            .help("sylvia-iot-auth host (ex: http://localhost:1080/auth)")
142            .num_args(1),
143    )
144    .arg(
145        Arg::new("broker.db.engine")
146            .long("broker.db.engine")
147            .help("database engine")
148            .num_args(1)
149            .value_parser([DbEngine::MONGODB, DbEngine::SQLITE]),
150    )
151    .arg(
152        Arg::new("broker.db.mongodb.url")
153            .long("broker.db.mongodb.url")
154            .help("MongoDB URL (scheme://[username][:password][@][host][:port]")
155            .num_args(1),
156    )
157    .arg(
158        Arg::new("broker.db.mongodb.database")
159            .long("broker.db.mongodb.database")
160            .help("database nane")
161            .num_args(1),
162    )
163    .arg(
164        Arg::new("broker.db.mongodb.poolsize")
165            .long("broker.db.mongodb.poolsize")
166            .help("connection pool size")
167            .num_args(1)
168            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u32::MAX as u64)),
169    )
170    .arg(
171        Arg::new("broker.db.sqlite.path")
172            .long("broker.db.sqlite.path")
173            .help("SQLite path")
174            .num_args(1),
175    )
176    .arg(
177        Arg::new("broker.cache.engine")
178            .long("broker.cache.engine")
179            .help("cache engine")
180            .num_args(1)
181            .value_parser([CacheEngine::MEMORY, CacheEngine::NONE]),
182    )
183    .arg(
184        Arg::new("broker.cache.memory.device")
185            .long("broker.cache.memory.device")
186            .help("Device cache size")
187            .num_args(1)
188            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
189    )
190    .arg(
191        Arg::new("broker.cache.memory.device-route")
192            .long("broker.cache.memory.device-route")
193            .help("Device route cache size")
194            .num_args(1)
195            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
196    )
197    .arg(
198        Arg::new("broker.cache.memory.network-route")
199            .long("broker.cache.memory.network-route")
200            .help("Network route cache size")
201            .num_args(1)
202            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
203    )
204    .arg(
205        Arg::new("broker.mq.prefetch")
206            .long("broker.mq.prefetch")
207            .help("AMQP prefetch")
208            .num_args(1)
209            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
210    )
211    .arg(
212        Arg::new("broker.mq.persistent")
213            .long("broker.mq.persistent")
214            .help("AMQP persistent")
215            .num_args(1)
216            .value_parser(BoolValueParser::new()),
217    )
218    .arg(
219        Arg::new("broker.mq.sharedprefix")
220            .long("broker.mq.sharedprefix")
221            .help("MQTT shared subscription prefix")
222            .num_args(1),
223    )
224    .arg(
225        Arg::new("broker.mq-channels.unit.url")
226            .long("broker.mq-channels.unit.url")
227            .help("URL of `broker.ctrl.unit` channel")
228            .num_args(1),
229    )
230    .arg(
231        Arg::new("broker.mq-channels.unit.prefetch")
232            .long("broker.mq-channels.unit.prefetch")
233            .help("AMQP prefetch for `broker.ctrl.unit` channel")
234            .num_args(1)
235            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
236    )
237    .arg(
238        Arg::new("broker.mq-channels.application.url")
239            .long("broker.mq-channels.application.url")
240            .help("URL of `broker.ctrl.application` channel")
241            .num_args(1),
242    )
243    .arg(
244        Arg::new("broker.mq-channels.application.prefetch")
245            .long("broker.mq-channels.application.prefetch")
246            .help("AMQP prefetch for `broker.ctrl.application` channel")
247            .num_args(1)
248            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
249    )
250    .arg(
251        Arg::new("broker.mq-channels.network.url")
252            .long("broker.mq-channels.network.url")
253            .help("URL of `broker.ctrl.network` channel")
254            .num_args(1),
255    )
256    .arg(
257        Arg::new("broker.mq-channels.network.prefetch")
258            .long("broker.mq-channels.network.prefetch")
259            .help("AMQP prefetch for `broker.ctrl.network` channel")
260            .num_args(1)
261            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
262    )
263    .arg(
264        Arg::new("broker.mq-channels.device.url")
265            .long("broker.mq-channels.device.url")
266            .help("URL of `broker.ctrl.device` channel")
267            .num_args(1),
268    )
269    .arg(
270        Arg::new("broker.mq-channels.device.prefetch")
271            .long("broker.mq-channels.device.prefetch")
272            .help("AMQP prefetch for `broker.ctrl.device` channel")
273            .num_args(1)
274            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
275    )
276    .arg(
277        Arg::new("broker.mq-channels.device-route.url")
278            .long("broker.mq-channels.device-route.url")
279            .help("URL of `broker.ctrl.device-route` channel")
280            .num_args(1),
281    )
282    .arg(
283        Arg::new("broker.mq-channels.device-route.prefetch")
284            .long("broker.mq-channels.device-route.prefetch")
285            .help("AMQP prefetch for `broker.ctrl.device-route` channel")
286            .num_args(1)
287            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
288    )
289    .arg(
290        Arg::new("broker.mq-channels.network-route.url")
291            .long("broker.mq-channels.network-route.url")
292            .help("URL of `broker.ctrl.network-route` channel")
293            .num_args(1),
294    )
295    .arg(
296        Arg::new("broker.mq-channels.network-route.prefetch")
297            .long("broker.mq-channels.network-route.prefetch")
298            .help("AMQP prefetch for `broker.ctrl.network-route` channel")
299            .num_args(1)
300            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
301    )
302    .arg(
303        Arg::new("broker.mq-channels.data.url")
304            .long("broker.mq-channels.data.url")
305            .help("URL of `broker.data` channel")
306            .num_args(1),
307    )
308    .arg(
309        Arg::new("broker.mq-channels.data.persistent")
310            .long("broker.mq-channels.data.persistent")
311            .help("AMQP persistent for `broker.data` channel")
312            .num_args(1)
313            .value_parser(BoolValueParser::new()),
314    )
315    .arg(
316        Arg::new("broker.api-scopes")
317            .long("broker.api-scopes")
318            .help("API scopes")
319            .num_args(0..),
320    )
321}
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.
327pub fn read_args(args: &ArgMatches) -> Config {
328    apply_default(&Config {
329        auth: match args.get_one::<String>("broker.auth") {
330            None => match env::var("BROKER_AUTH") {
331                Err(_) => None,
332                Ok(v) => Some(v),
333            },
334            Some(v) => Some(v.clone()),
335        },
336        db: Some(Db {
337            engine: match args.get_one::<String>("broker.db.engine") {
338                None => match env::var("BROKER_DB_ENGINE") {
339                    Err(_) => None,
340                    Ok(v) => Some(v),
341                },
342                Some(v) => Some(v.clone()),
343            },
344            mongodb: Some(MongoDb {
345                url: match args.get_one::<String>("broker.db.mongodb.url") {
346                    None => match env::var("BROKER_DB_MONGODB_URL") {
347                        Err(_) => None,
348                        Ok(v) => Some(v),
349                    },
350                    Some(v) => Some(v.clone()),
351                },
352                database: match args.get_one::<String>("broker.db.mongodb.database") {
353                    None => match env::var("BROKER_DB_MONGODB_DATABASE") {
354                        Err(_) => None,
355                        Ok(v) => Some(v),
356                    },
357                    Some(v) => Some(v.clone()),
358                },
359                pool_size: match args.get_one::<u64>("broker.db.mongodb.poolsize") {
360                    None => match env::var("BROKER_DB_MONGODB_POOLSIZE") {
361                        Err(_) => None,
362                        Ok(v) => match v.parse::<u32>() {
363                            Err(_) => None,
364                            Ok(v) => Some(v),
365                        },
366                    },
367                    Some(v) => Some(*v as u32),
368                },
369            }),
370            sqlite: Some(Sqlite {
371                path: match args.get_one::<String>("broker.db.sqlite.path") {
372                    None => match env::var("BROKER_DB_SQLITE_PATH") {
373                        Err(_) => None,
374                        Ok(v) => Some(v),
375                    },
376                    Some(v) => Some(v.clone()),
377                },
378            }),
379        }),
380        cache: Some(Cache {
381            engine: match args.get_one::<String>("broker.cache.engine") {
382                None => match env::var("BROKER_CACHE_ENGINE") {
383                    Err(_) => None,
384                    Ok(v) => Some(v),
385                },
386                Some(v) => Some(v.clone()),
387            },
388            memory: Some(MemoryCache {
389                device: match args.get_one::<u64>("broker.cache.memory.device") {
390                    None => match env::var("BROKER_CACHE_MEMORY_DEVICE") {
391                        Err(_) => None,
392                        Ok(v) => match v.parse::<usize>() {
393                            Err(_) => None,
394                            Ok(v) => Some(v),
395                        },
396                    },
397                    Some(v) => Some(*v as usize),
398                },
399                device_route: match args.get_one::<u64>("broker.cache.memory.device-route") {
400                    None => match env::var("BROKER_CACHE_MEMORY_DEVICE_ROUTE") {
401                        Err(_) => None,
402                        Ok(v) => match v.parse::<usize>() {
403                            Err(_) => None,
404                            Ok(v) => Some(v),
405                        },
406                    },
407                    Some(v) => Some(*v as usize),
408                },
409                network_route: match args.get_one::<u64>("broker.cache.memory.network-route") {
410                    None => match env::var("BROKER_CACHE_MEMORY_NETWORK_ROUTE") {
411                        Err(_) => None,
412                        Ok(v) => match v.parse::<usize>() {
413                            Err(_) => None,
414                            Ok(v) => Some(v),
415                        },
416                    },
417                    Some(v) => Some(*v as usize),
418                },
419            }),
420        }),
421        mq: Some(Mq {
422            prefetch: match args.get_one::<u64>("broker.mq.prefetch") {
423                None => match env::var("BROKER_MQ_PREFETCH") {
424                    Err(_) => None,
425                    Ok(v) => match v.parse::<u16>() {
426                        Err(_) => None,
427                        Ok(v) => Some(v),
428                    },
429                },
430                Some(v) => Some(*v as u16),
431            },
432            persistent: match args.get_one::<bool>("broker.mq.persistent") {
433                None => match env::var("BROKER_MQ_PERSISTENT") {
434                    Err(_) => None,
435                    Ok(v) => match v.parse::<bool>() {
436                        Err(_) => None,
437                        Ok(v) => Some(v),
438                    },
439                },
440                Some(v) => Some(*v as bool),
441            },
442            shared_prefix: match args.get_one::<String>("broker.mq.sharedprefix") {
443                None => match env::var("BROKER_MQ_SHAREDPREFIX") {
444                    Err(_) => None,
445                    Ok(v) => Some(v),
446                },
447                Some(v) => Some(v.clone()),
448            },
449        }),
450        mq_channels: Some(MqChannels {
451            unit: Some(BrokerCtrl {
452                url: match args.get_one::<String>("broker.mq-channels.unit.url") {
453                    None => match env::var("BROKER_MQCHANNELS_UNIT_URL") {
454                        Err(_) => None,
455                        Ok(v) => Some(v),
456                    },
457                    Some(v) => Some(v.clone()),
458                },
459                prefetch: match args.get_one::<u64>("broker.mq-channels.unit.prefetch") {
460                    None => match env::var("BROKER_MQCHANNELS_UNIT_PREFETCH") {
461                        Err(_) => None,
462                        Ok(v) => match v.parse::<u16>() {
463                            Err(_) => None,
464                            Ok(v) => Some(v),
465                        },
466                    },
467                    Some(v) => Some(*v as u16),
468                },
469            }),
470            application: Some(BrokerCtrl {
471                url: match args.get_one::<String>("broker.mq-channels.application.url") {
472                    None => match env::var("BROKER_MQCHANNELS_APPLICATION_URL") {
473                        Err(_) => None,
474                        Ok(v) => Some(v),
475                    },
476                    Some(v) => Some(v.clone()),
477                },
478                prefetch: match args.get_one::<u64>("broker.mq-channels.application.prefetch") {
479                    None => match env::var("BROKER_MQCHANNELS_APPLICATION_PREFETCH") {
480                        Err(_) => None,
481                        Ok(v) => match v.parse::<u16>() {
482                            Err(_) => None,
483                            Ok(v) => Some(v),
484                        },
485                    },
486                    Some(v) => Some(*v as u16),
487                },
488            }),
489            network: Some(BrokerCtrl {
490                url: match args.get_one::<String>("broker.mq-channels.network.url") {
491                    None => match env::var("BROKER_MQCHANNELS_NETWORK_URL") {
492                        Err(_) => None,
493                        Ok(v) => Some(v),
494                    },
495                    Some(v) => Some(v.clone()),
496                },
497                prefetch: match args.get_one::<u64>("broker.mq-channels.network.prefetch") {
498                    None => match env::var("BROKER_MQCHANNELS_NETWORK_PREFETCH") {
499                        Err(_) => None,
500                        Ok(v) => match v.parse::<u16>() {
501                            Err(_) => None,
502                            Ok(v) => Some(v),
503                        },
504                    },
505                    Some(v) => Some(*v as u16),
506                },
507            }),
508            device: Some(BrokerCtrl {
509                url: match args.get_one::<String>("broker.mq-channels.device.url") {
510                    None => match env::var("BROKER_MQCHANNELS_DEVICE_URL") {
511                        Err(_) => None,
512                        Ok(v) => Some(v),
513                    },
514                    Some(v) => Some(v.clone()),
515                },
516                prefetch: match args.get_one::<u64>("broker.mq-channels.device.prefetch") {
517                    None => match env::var("BROKER_MQCHANNELS_DEVICE_PREFETCH") {
518                        Err(_) => None,
519                        Ok(v) => match v.parse::<u16>() {
520                            Err(_) => None,
521                            Ok(v) => Some(v),
522                        },
523                    },
524                    Some(v) => Some(*v as u16),
525                },
526            }),
527            device_route: Some(BrokerCtrl {
528                url: match args.get_one::<String>("broker.mq-channels.device-route.url") {
529                    None => match env::var("BROKER_MQCHANNELS_DEVICE_ROUTE_URL") {
530                        Err(_) => None,
531                        Ok(v) => Some(v),
532                    },
533                    Some(v) => Some(v.clone()),
534                },
535                prefetch: match args.get_one::<u64>("broker.mq-channels.device-route.prefetch") {
536                    None => match env::var("BROKER_MQCHANNELS_DEVICE_ROUTE_PREFETCH") {
537                        Err(_) => None,
538                        Ok(v) => match v.parse::<u16>() {
539                            Err(_) => None,
540                            Ok(v) => Some(v),
541                        },
542                    },
543                    Some(v) => Some(*v as u16),
544                },
545            }),
546            network_route: Some(BrokerCtrl {
547                url: match args.get_one::<String>("broker.mq-channels.network-route.url") {
548                    None => match env::var("BROKER_MQCHANNELS_NETWORK_ROUTE_URL") {
549                        Err(_) => None,
550                        Ok(v) => Some(v),
551                    },
552                    Some(v) => Some(v.clone()),
553                },
554                prefetch: match args.get_one::<u64>("broker.mq-channels.network-route.prefetch") {
555                    None => match env::var("BROKER_MQCHANNELS_NETWORK_ROUTE_PREFETCH") {
556                        Err(_) => None,
557                        Ok(v) => match v.parse::<u16>() {
558                            Err(_) => None,
559                            Ok(v) => Some(v),
560                        },
561                    },
562                    Some(v) => Some(*v as u16),
563                },
564            }),
565            data: Some(BrokerData {
566                url: match args.get_one::<String>("broker.mq-channels.data.url") {
567                    None => match env::var("BROKER_MQCHANNELS_DATA_URL") {
568                        Err(_) => None,
569                        Ok(v) => Some(v),
570                    },
571                    Some(v) => Some(v.clone()),
572                },
573                persistent: match args.get_one::<bool>("broker.mq-channels.data.persistent") {
574                    None => match env::var("BROKER_MQCHANNELS_DATA_PERSISTENT") {
575                        Err(_) => None,
576                        Ok(v) => match v.parse::<bool>() {
577                            Err(_) => None,
578                            Ok(v) => Some(v),
579                        },
580                    },
581                    Some(v) => Some(*v as bool),
582                },
583            }),
584        }),
585        api_scopes: match args.get_one::<String>("broker.api-scopes") {
586            None => match env::var("BROKER_API_SCOPES") {
587                Err(_) => None,
588                Ok(v) => match v.len() {
589                    0 => None,
590                    _ => match serde_json::from_str::<HashMap<String, Vec<String>>>(v.as_str()) {
591                        Err(_) => None,
592                        Ok(v) => Some(v),
593                    },
594                },
595            },
596            Some(v) => match v.len() {
597                0 => None,
598                _ => match serde_json::from_str::<HashMap<String, Vec<String>>>(v.as_str()) {
599                    Err(_) => None,
600                    Ok(v) => Some(v),
601                },
602            },
603        },
604    })
605}
606
607/// Fill missing configuration with default values.
608pub fn apply_default(config: &Config) -> Config {
609    Config {
610        auth: match config.auth.as_ref() {
611            None => Some(DEF_AUTH.to_string()),
612            Some(auth) => Some(auth.clone()),
613        },
614        db: match config.db.as_ref() {
615            None => Some(Db {
616                engine: Some(DEF_ENGINE.to_string()),
617                mongodb: Some(MongoDb {
618                    url: Some(DEF_MONGODB_URL.to_string()),
619                    database: Some(DEF_MONGODB_DB.to_string()),
620                    pool_size: None,
621                }),
622                sqlite: Some(Sqlite {
623                    path: Some(DEF_SQLITE_PATH.to_string()),
624                }),
625            }),
626            Some(db) => Some(Db {
627                engine: match db.engine.as_ref() {
628                    None => Some(DEF_ENGINE.to_string()),
629                    Some(engine) => match engine.as_str() {
630                        DbEngine::MONGODB => Some(DbEngine::MONGODB.to_string()),
631                        DbEngine::SQLITE => Some(DbEngine::SQLITE.to_string()),
632                        _ => Some(DEF_ENGINE.to_string()),
633                    },
634                },
635                mongodb: match db.mongodb.as_ref() {
636                    None => Some(MongoDb {
637                        url: Some(DEF_MONGODB_URL.to_string()),
638                        database: Some(DEF_MONGODB_DB.to_string()),
639                        pool_size: None,
640                    }),
641                    Some(mongodb) => Some(MongoDb {
642                        url: match mongodb.url.as_ref() {
643                            None => Some(DEF_MONGODB_URL.to_string()),
644                            Some(url) => Some(url.to_string()),
645                        },
646                        database: match mongodb.database.as_ref() {
647                            None => Some(DEF_MONGODB_DB.to_string()),
648                            Some(database) => Some(database.to_string()),
649                        },
650                        pool_size: mongodb.pool_size,
651                    }),
652                },
653                sqlite: match db.sqlite.as_ref() {
654                    None => Some(Sqlite {
655                        path: Some(DEF_SQLITE_PATH.to_string()),
656                    }),
657                    Some(sqlite) => Some(Sqlite {
658                        path: match sqlite.path.as_ref() {
659                            None => Some(DEF_SQLITE_PATH.to_string()),
660                            Some(path) => Some(path.to_string()),
661                        },
662                    }),
663                },
664            }),
665        },
666        cache: match config.cache.as_ref() {
667            None => Some(Cache {
668                engine: Some(DEF_CACHE_ENGINE.to_string()),
669                memory: Some(MemoryCache {
670                    device: Some(DEF_MEMORY_DEVICE),
671                    device_route: Some(DEF_MEMORY_DEVICE_ROUTE),
672                    network_route: Some(DEF_MEMORY_NETWORK_ROUTE),
673                }),
674            }),
675            Some(cache) => Some(Cache {
676                engine: match cache.engine.as_ref() {
677                    None => Some(DEF_CACHE_ENGINE.to_string()),
678                    Some(engine) => match engine.as_str() {
679                        CacheEngine::MEMORY => Some(CacheEngine::MEMORY.to_string()),
680                        _ => Some(DEF_CACHE_ENGINE.to_string()),
681                    },
682                },
683                memory: match cache.memory.as_ref() {
684                    None => Some(MemoryCache {
685                        device: Some(DEF_MEMORY_DEVICE),
686                        device_route: Some(DEF_MEMORY_DEVICE_ROUTE),
687                        network_route: Some(DEF_MEMORY_NETWORK_ROUTE),
688                    }),
689                    Some(memory) => Some(MemoryCache {
690                        device: match memory.device {
691                            None | Some(0) => Some(DEF_MEMORY_DEVICE),
692                            Some(v) => Some(v),
693                        },
694                        device_route: match memory.device_route {
695                            None | Some(0) => Some(DEF_MEMORY_DEVICE_ROUTE),
696                            Some(v) => Some(v),
697                        },
698                        network_route: match memory.network_route {
699                            None | Some(0) => Some(DEF_MEMORY_NETWORK_ROUTE),
700                            Some(v) => Some(v),
701                        },
702                    }),
703                },
704            }),
705        },
706        mq: match config.mq.as_ref() {
707            None => Some(Mq {
708                prefetch: Some(DEF_MQ_PREFETCH),
709                persistent: Some(DEF_MQ_PERSISTENT),
710                shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
711            }),
712            Some(mq) => Some(Mq {
713                prefetch: match mq.prefetch {
714                    None | Some(0) => Some(DEF_MQ_PREFETCH),
715                    Some(prefetch) => Some(prefetch),
716                },
717                persistent: match mq.persistent {
718                    None => Some(DEF_MQ_PERSISTENT),
719                    Some(persistent) => Some(persistent),
720                },
721                shared_prefix: match mq.shared_prefix.as_ref() {
722                    None => Some(DEF_MQ_SHAREDPREFIX.to_string()),
723                    Some(shared_prefix) => Some(shared_prefix.to_string()),
724                },
725            }),
726        },
727        mq_channels: match config.mq_channels.as_ref() {
728            None => Some(MqChannels {
729                unit: Some(BrokerCtrl {
730                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
731                    prefetch: Some(DEF_MQ_PREFETCH),
732                }),
733                application: Some(BrokerCtrl {
734                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
735                    prefetch: Some(DEF_MQ_PREFETCH),
736                }),
737                network: Some(BrokerCtrl {
738                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
739                    prefetch: Some(DEF_MQ_PREFETCH),
740                }),
741                device: Some(BrokerCtrl {
742                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
743                    prefetch: Some(DEF_MQ_PREFETCH),
744                }),
745                device_route: Some(BrokerCtrl {
746                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
747                    prefetch: Some(DEF_MQ_PREFETCH),
748                }),
749                network_route: Some(BrokerCtrl {
750                    url: Some(DEF_MQ_CHANNEL_URL.to_string()),
751                    prefetch: Some(DEF_MQ_PREFETCH),
752                }),
753                data: None,
754            }),
755            Some(mq_channels) => Some(MqChannels {
756                unit: match mq_channels.unit.as_ref() {
757                    None => Some(BrokerCtrl {
758                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
759                        prefetch: Some(DEF_MQ_PREFETCH),
760                    }),
761                    Some(channel) => Some(BrokerCtrl {
762                        url: match channel.url.as_ref() {
763                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
764                            Some(url) => Some(url.to_string()),
765                        },
766                        prefetch: match channel.prefetch {
767                            None => Some(DEF_MQ_PREFETCH),
768                            Some(prefetch) => Some(prefetch),
769                        },
770                    }),
771                },
772                application: match mq_channels.application.as_ref() {
773                    None => Some(BrokerCtrl {
774                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
775                        prefetch: Some(DEF_MQ_PREFETCH),
776                    }),
777                    Some(channel) => Some(BrokerCtrl {
778                        url: match channel.url.as_ref() {
779                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
780                            Some(url) => Some(url.to_string()),
781                        },
782                        prefetch: match channel.prefetch {
783                            None => Some(DEF_MQ_PREFETCH),
784                            Some(prefetch) => Some(prefetch),
785                        },
786                    }),
787                },
788                network: match mq_channels.network.as_ref() {
789                    None => Some(BrokerCtrl {
790                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
791                        prefetch: Some(DEF_MQ_PREFETCH),
792                    }),
793                    Some(channel) => Some(BrokerCtrl {
794                        url: match channel.url.as_ref() {
795                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
796                            Some(url) => Some(url.to_string()),
797                        },
798                        prefetch: match channel.prefetch {
799                            None => Some(DEF_MQ_PREFETCH),
800                            Some(prefetch) => Some(prefetch),
801                        },
802                    }),
803                },
804                device: match mq_channels.device.as_ref() {
805                    None => Some(BrokerCtrl {
806                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
807                        prefetch: Some(DEF_MQ_PREFETCH),
808                    }),
809                    Some(channel) => Some(BrokerCtrl {
810                        url: match channel.url.as_ref() {
811                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
812                            Some(url) => Some(url.to_string()),
813                        },
814                        prefetch: match channel.prefetch {
815                            None => Some(DEF_MQ_PREFETCH),
816                            Some(prefetch) => Some(prefetch),
817                        },
818                    }),
819                },
820                device_route: match mq_channels.device_route.as_ref() {
821                    None => Some(BrokerCtrl {
822                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
823                        prefetch: Some(DEF_MQ_PREFETCH),
824                    }),
825                    Some(channel) => Some(BrokerCtrl {
826                        url: match channel.url.as_ref() {
827                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
828                            Some(url) => Some(url.to_string()),
829                        },
830                        prefetch: match channel.prefetch {
831                            None => Some(DEF_MQ_PREFETCH),
832                            Some(prefetch) => Some(prefetch),
833                        },
834                    }),
835                },
836                network_route: match mq_channels.network_route.as_ref() {
837                    None => Some(BrokerCtrl {
838                        url: Some(DEF_MQ_CHANNEL_URL.to_string()),
839                        prefetch: Some(DEF_MQ_PREFETCH),
840                    }),
841                    Some(channel) => Some(BrokerCtrl {
842                        url: match channel.url.as_ref() {
843                            None => Some(DEF_MQ_CHANNEL_URL.to_string()),
844                            Some(url) => Some(url.to_string()),
845                        },
846                        prefetch: match channel.prefetch {
847                            None => Some(DEF_MQ_PREFETCH),
848                            Some(prefetch) => Some(prefetch),
849                        },
850                    }),
851                },
852                data: match mq_channels.data.as_ref() {
853                    None => None,
854                    Some(channel) => Some(BrokerData {
855                        url: match channel.url.as_ref() {
856                            None => None,
857                            Some(url) => Some(url.to_string()),
858                        },
859                        persistent: match channel.persistent {
860                            None => Some(DEF_MQ_PERSISTENT),
861                            Some(persistent) => Some(persistent),
862                        },
863                    }),
864                },
865            }),
866        },
867        api_scopes: match config.api_scopes.as_ref() {
868            None => Some(HashMap::new()),
869            Some(scopes) => Some(scopes.clone()),
870        },
871    }
872}