Skip to main content

opcua/core/
config.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5use std::fs::File;
6use std::io::{Read, Write};
7use std::path::Path;
8use std::result::Result;
9
10use serde;
11use serde_yaml;
12
13use crate::types::{
14    service_types::{ApplicationDescription, ApplicationType},
15    LocalizedText, UAString,
16};
17
18/// A trait that handles the loading / saving and validity of configuration information for a
19/// client and/or server.
20pub trait Config: serde::Serialize {
21    fn save(&self, path: &Path) -> Result<(), ()> {
22        if self.is_valid() {
23            let s = serde_yaml::to_string(&self).unwrap();
24            if let Ok(mut f) = File::create(path) {
25                let result = f.write_all(s.as_bytes());
26                if result.is_ok() {
27                    return Ok(());
28                } else {
29                    error!("Could not save config - error = {:?}", result.unwrap_err())
30                }
31            } else {
32                error!("Cannot create the path to save the config");
33            }
34        } else {
35            error!("Config isn't valid and won't be saved");
36        }
37        Err(())
38    }
39
40    fn load<A>(path: &Path) -> Result<A, ()>
41    where
42        for<'de> A: Config + serde::Deserialize<'de>,
43    {
44        if let Ok(mut f) = File::open(path) {
45            let mut s = String::new();
46            if f.read_to_string(&mut s).is_ok() {
47                serde_yaml::from_str(&s).map_err(|err| {
48                    error!(
49                        "Cannot deserialize configuration from {}, error reason: {}",
50                        path.to_string_lossy(),
51                        err.to_string()
52                    );
53                })
54            } else {
55                error!(
56                    "Cannot read configuration file {} to string",
57                    path.to_string_lossy()
58                );
59                Err(())
60            }
61        } else {
62            error!("Cannot open configuration file {}", path.to_string_lossy());
63            Err(())
64        }
65    }
66
67    fn is_valid(&self) -> bool;
68
69    fn application_name(&self) -> UAString;
70
71    fn application_uri(&self) -> UAString;
72
73    fn product_uri(&self) -> UAString;
74
75    fn application_type(&self) -> ApplicationType;
76
77    fn discovery_urls(&self) -> Option<Vec<UAString>> {
78        None
79    }
80
81    fn application_description(&self) -> ApplicationDescription {
82        ApplicationDescription {
83            application_uri: self.application_uri(),
84            application_name: LocalizedText::new("", self.application_name().as_ref()),
85            application_type: self.application_type(),
86            product_uri: self.product_uri(),
87            gateway_server_uri: UAString::null(),
88            discovery_profile_uri: UAString::null(),
89            discovery_urls: self.discovery_urls(),
90        }
91    }
92}