mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
move confy here
This commit is contained in:
14
libs/confy/.gitignore
vendored
Normal file
14
libs/confy/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
26
libs/confy/Cargo.toml
Normal file
26
libs/confy/Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "confy"
|
||||
version = "0.4.1"
|
||||
authors = ["Katharina Fey <kookie@spacekookie.de>"]
|
||||
description = "Boilerplate-free configuration management"
|
||||
license = "MIT/X11 OR Apache-2.0"
|
||||
documentation = "https://docs.rs/confy"
|
||||
repository = "https://github.com/rust-clique/confy"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = "^1.0"
|
||||
toml = { version = "^0.5", optional = true }
|
||||
directories = "^2.0"
|
||||
serde_yaml = { version = "0.8", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["toml_conf"]
|
||||
toml_conf = ["toml"]
|
||||
yaml_conf = ["serde_yaml"]
|
||||
|
||||
[[example]]
|
||||
name = "simple"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = "^1.0"
|
||||
21
libs/confy/LICENSE
Normal file
21
libs/confy/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 rust-clique
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
39
libs/confy/README.md
Normal file
39
libs/confy/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# confy
|
||||
|
||||
Chat with us: [Discord](https://discord.gg/dwq4Zme)
|
||||
|
||||
Zero-boilerplate configuration management.
|
||||
|
||||
Focus on storing the right data, instead of worrying about how or where to store it.
|
||||
|
||||
```rust
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||
struct MyConfig {
|
||||
version: u8,
|
||||
api_key: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), ::std::io::Error> {
|
||||
let cfg: MyConfig = confy::load("my-app-name")?;
|
||||
dbg!(cfg);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Using yaml
|
||||
Enabling the `yaml_conf` feature while disabling the default `toml_conf`
|
||||
feature causes confy to use a YAML config file instead of TOML.
|
||||
|
||||
```
|
||||
[dependencies.confy]
|
||||
features = ["yaml_conf"]
|
||||
default-features = false
|
||||
```
|
||||
|
||||
## Breakings changes
|
||||
Starting with version 0.4.0 the configuration file are stored in the expected place for your system. See the [`directories`] crates for more information.
|
||||
Before version 0.4.0, the configuration file was written in the current directory.
|
||||
|
||||
[`directories`]: https://crates.io/crates/directories
|
||||
29
libs/confy/examples/simple.rs
Normal file
29
libs/confy/examples/simple.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
//! The most simplest examples of how to use confy
|
||||
|
||||
extern crate confy;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct ConfyConfig {
|
||||
name: String,
|
||||
comfy: bool,
|
||||
foo: i64,
|
||||
}
|
||||
|
||||
impl Default for ConfyConfig {
|
||||
fn default() -> Self {
|
||||
ConfyConfig {
|
||||
name: "Unknown".to_string(),
|
||||
comfy: true,
|
||||
foo: 42,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), confy::ConfyError> {
|
||||
let cfg: ConfyConfig = confy::load("confy_simple_app")?;
|
||||
println!("{:#?}", cfg);
|
||||
Ok(())
|
||||
}
|
||||
300
libs/confy/src/lib.rs
Normal file
300
libs/confy/src/lib.rs
Normal file
@@ -0,0 +1,300 @@
|
||||
//! Zero-boilerplate configuration management
|
||||
//!
|
||||
//! ## Why?
|
||||
//!
|
||||
//! There are a lot of different requirements when
|
||||
//! selecting, loading and writing a config,
|
||||
//! depending on the operating system and other
|
||||
//! environment factors.
|
||||
//!
|
||||
//! In many applications this burden is left to you,
|
||||
//! the developer of an application, to figure out
|
||||
//! where to place the configuration files.
|
||||
//!
|
||||
//! This is where `confy` comes in.
|
||||
//!
|
||||
//! ## Idea
|
||||
//!
|
||||
//! `confy` takes care of figuring out operating system
|
||||
//! specific and environment paths before reading and
|
||||
//! writing a configuration.
|
||||
//!
|
||||
//! It gives you easy access to a configuration file
|
||||
//! which is mirrored into a Rust `struct` via [serde].
|
||||
//! This way you only need to worry about the layout of
|
||||
//! your configuration, not where and how to store it.
|
||||
//!
|
||||
//! [serde]: https://docs.rs/crates/serde
|
||||
//!
|
||||
//! `confy` uses the [`Default`] trait in Rust to automatically
|
||||
//! create a new configuration, if none is available to read
|
||||
//! from yet.
|
||||
//! This means that you can simply assume your application
|
||||
//! to have a configuration, which will be created with
|
||||
//! default values of your choosing, without requiring
|
||||
//! any special logic to handle creation.
|
||||
//!
|
||||
//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use serde_derive::{Serialize, Deserialize};
|
||||
//!
|
||||
//! #[derive(Serialize, Deserialize)]
|
||||
//! struct MyConfig {
|
||||
//! version: u8,
|
||||
//! api_key: String,
|
||||
//! }
|
||||
//!
|
||||
//! /// `MyConfig` implements `Default`
|
||||
//! impl ::std::default::Default for MyConfig {
|
||||
//! fn default() -> Self { Self { version: 0, api_key: "".into() } }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() -> Result<(), confy::ConfyError> {
|
||||
//! let cfg = confy::load("my-app-name")?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Updating the configuration is then done via the [`store`] function.
|
||||
//!
|
||||
//! [`store`]: fn.store.html
|
||||
//!
|
||||
|
||||
mod utils;
|
||||
use utils::*;
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use std::io::{ErrorKind::NotFound, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[cfg(not(any(feature = "toml_conf", feature = "yaml_conf")))]
|
||||
compile_error!("Exactly one config language feature must be enabled to use \
|
||||
confy. Please enable one of either the `toml_conf` or `yaml_conf` \
|
||||
features.");
|
||||
|
||||
#[cfg(all(feature = "toml_conf", feature = "yaml_conf"))]
|
||||
compile_error!("Exactly one config language feature must be enabled to compile \
|
||||
confy. Please disable one of either the `toml_conf` or `yaml_conf` features. \
|
||||
NOTE: `toml_conf` is a default feature, so disabling it might mean switching off \
|
||||
default features for confy in your Cargo.toml");
|
||||
|
||||
#[cfg(all(feature = "toml_conf", not(feature = "yaml_conf")))]
|
||||
const EXTENSION: &str = "toml";
|
||||
|
||||
#[cfg(feature = "yaml_conf")]
|
||||
const EXTENSION: &str = "yml";
|
||||
|
||||
/// Load an application configuration from disk
|
||||
///
|
||||
/// A new configuration file is created with default values if none
|
||||
/// exists.
|
||||
///
|
||||
/// Errors that are returned from this function are I/O related,
|
||||
/// for example if the writing of the new configuration fails
|
||||
/// or `confy` encounters an operating system or environment
|
||||
/// that it does not support.
|
||||
///
|
||||
/// **Note:** The type of configuration needs to be declared in some way
|
||||
/// that is inferrable by the compiler. Also note that your
|
||||
/// configuration needs to implement `Default`.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use confy::ConfyError;
|
||||
/// # use serde_derive::{Serialize, Deserialize};
|
||||
/// # fn main() -> Result<(), ConfyError> {
|
||||
/// #[derive(Default, Serialize, Deserialize)]
|
||||
/// struct MyConfig {}
|
||||
///
|
||||
/// let cfg: MyConfig = confy::load("my-app-name")?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn load<T: Serialize + DeserializeOwned + Default>(name: &str) -> Result<T, ConfyError> {
|
||||
let project = ProjectDirs::from("rs", "", name).ok_or(ConfyError::BadConfigDirectoryStr)?;
|
||||
|
||||
let config_dir_str = get_configuration_directory_str(&project)?;
|
||||
|
||||
let path: PathBuf = [config_dir_str, &format!("{}.{}", name, EXTENSION)].iter().collect();
|
||||
|
||||
load_path(path)
|
||||
}
|
||||
|
||||
/// Load an application configuration from a specified path.
|
||||
///
|
||||
/// This is an alternate version of [`load`] that allows the specification of
|
||||
/// an aritrary path instead of a system one. For more information on errors
|
||||
/// and behavior, see [`load`]'s documentation.
|
||||
///
|
||||
/// [`load`]: fn.load.html
|
||||
pub fn load_path<T: Serialize + DeserializeOwned + Default>(path: impl AsRef<Path>) -> Result<T, ConfyError> {
|
||||
match File::open(&path) {
|
||||
Ok(mut cfg) => {
|
||||
let cfg_string = cfg
|
||||
.get_string()
|
||||
.map_err(ConfyError::ReadConfigurationFileError)?;
|
||||
|
||||
#[cfg(feature = "toml_conf")] {
|
||||
let cfg_data = toml::from_str(&cfg_string);
|
||||
cfg_data.map_err(ConfyError::BadTomlData)
|
||||
}
|
||||
#[cfg(feature = "yaml_conf")] {
|
||||
let cfg_data = serde_yaml::from_str(&cfg_string);
|
||||
cfg_data.map_err(ConfyError::BadYamlData)
|
||||
}
|
||||
|
||||
}
|
||||
Err(ref e) if e.kind() == NotFound => {
|
||||
if let Some(parent) = path.as_ref().parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(ConfyError::DirectoryCreationFailed)?;
|
||||
}
|
||||
store_path(path, T::default())?;
|
||||
Ok(T::default())
|
||||
}
|
||||
Err(e) => Err(ConfyError::GeneralLoadError(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// The errors the confy crate can encounter.
|
||||
#[derive(Debug)]
|
||||
pub enum ConfyError {
|
||||
#[cfg(feature = "toml_conf")]
|
||||
BadTomlData(toml::de::Error),
|
||||
|
||||
#[cfg(feature = "yaml_conf")]
|
||||
BadYamlData(serde_yaml::Error),
|
||||
|
||||
DirectoryCreationFailed(std::io::Error),
|
||||
GeneralLoadError(std::io::Error),
|
||||
BadConfigDirectoryStr,
|
||||
|
||||
#[cfg(feature = "toml_conf")]
|
||||
SerializeTomlError(toml::ser::Error),
|
||||
|
||||
#[cfg(feature = "yaml_conf")]
|
||||
SerializeYamlError(serde_yaml::Error),
|
||||
|
||||
WriteConfigurationFileError(std::io::Error),
|
||||
ReadConfigurationFileError(std::io::Error),
|
||||
OpenConfigurationFileError(std::io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConfyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
#[cfg(feature = "toml_conf")]
|
||||
ConfyError::BadTomlData(e) => write!(f, "Bad TOML data: {}", e),
|
||||
#[cfg(feature = "toml_conf")]
|
||||
ConfyError::SerializeTomlError(_) => write!(f, "Failed to serialize configuration data into TOML."),
|
||||
|
||||
#[cfg(feature = "yaml_conf")]
|
||||
ConfyError::BadYamlData(e) => write!(f, "Bad YAML data: {}", e),
|
||||
#[cfg(feature = "yaml_conf")]
|
||||
ConfyError::SerializeYamlError(_) => write!(f, "Failed to serialize configuration data into YAML."),
|
||||
|
||||
ConfyError::DirectoryCreationFailed(e) => write!(f, "Failed to create directory: {}", e),
|
||||
ConfyError::GeneralLoadError(_) => write!(f, "Failed to load configuration file."),
|
||||
ConfyError::BadConfigDirectoryStr => write!(f, "Failed to convert directory name to str."),
|
||||
ConfyError::WriteConfigurationFileError(_) => write!(f, "Failed to write configuration file."),
|
||||
ConfyError::ReadConfigurationFileError(_) => write!(f, "Failed to read configuration file."),
|
||||
ConfyError::OpenConfigurationFileError(_) => write!(f, "Failed to open configuration file."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ConfyError {}
|
||||
|
||||
/// Save changes made to a configuration object
|
||||
///
|
||||
/// This function will update a configuration,
|
||||
/// with the provided values, and create a new one,
|
||||
/// if none exists.
|
||||
///
|
||||
/// You can also use this function to create a new configuration
|
||||
/// with different initial values than which are provided
|
||||
/// by your `Default` trait implementation, or if your
|
||||
/// configuration structure _can't_ implement `Default`.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use serde_derive::{Serialize, Deserialize};
|
||||
/// # use confy::ConfyError;
|
||||
/// # fn main() -> Result<(), ConfyError> {
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// struct MyConf {}
|
||||
///
|
||||
/// let my_cfg = MyConf {};
|
||||
/// confy::store("my-app-name", my_cfg)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Errors returned are I/O errors related to not being
|
||||
/// able to write the configuration file or if `confy`
|
||||
/// encounters an operating system or environment it does
|
||||
/// not support.
|
||||
pub fn store<T: Serialize>(name: &str, cfg: T) -> Result<(), ConfyError> {
|
||||
let project = ProjectDirs::from("rs", "", name).ok_or(ConfyError::BadConfigDirectoryStr)?;
|
||||
fs::create_dir_all(project.config_dir()).map_err(ConfyError::DirectoryCreationFailed)?;
|
||||
|
||||
let config_dir_str = get_configuration_directory_str(&project)?;
|
||||
|
||||
let path: PathBuf = [config_dir_str, &format!("{}.{}", name, EXTENSION)].iter().collect();
|
||||
|
||||
store_path(path, cfg)
|
||||
}
|
||||
|
||||
/// Save changes made to a configuration object at a specified path
|
||||
///
|
||||
/// This is an alternate version of [`store`] that allows the specification of
|
||||
/// an aritrary path instead of a system one. For more information on errors
|
||||
/// and behavior, see [`store`]'s documentation.
|
||||
///
|
||||
/// [`store`]: fn.store.html
|
||||
pub fn store_path<T: Serialize>(path: impl AsRef<Path>, cfg: T) -> Result<(), ConfyError> {
|
||||
let path = path.as_ref();
|
||||
let mut path_tmp = path.to_path_buf();
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
let mut i = 0;
|
||||
loop {
|
||||
i += 1;
|
||||
path_tmp.set_extension(SystemTime::now().duration_since(UNIX_EPOCH).map(|x| x.as_nanos()).unwrap_or(i).to_string());
|
||||
if !path_tmp.exists() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut f = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(&path_tmp)
|
||||
.map_err(ConfyError::OpenConfigurationFileError)?;
|
||||
|
||||
let s;
|
||||
#[cfg(feature = "toml_conf")] {
|
||||
s = toml::to_string(&cfg).map_err(ConfyError::SerializeTomlError)?;
|
||||
}
|
||||
#[cfg(feature = "yaml_conf")] {
|
||||
s = serde_yaml::to_string(&cfg).map_err(ConfyError::SerializeYamlError)?;
|
||||
}
|
||||
|
||||
f.write_all(s.as_bytes())
|
||||
.map_err(ConfyError::WriteConfigurationFileError)?;
|
||||
std::fs::rename(path_tmp, path)
|
||||
.map_err(ConfyError::WriteConfigurationFileError)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_configuration_directory_str(project: &ProjectDirs) -> Result<&str, ConfyError> {
|
||||
let config_dir_option = project.config_dir().to_str();
|
||||
|
||||
match config_dir_option {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(ConfyError::BadConfigDirectoryStr),
|
||||
}
|
||||
}
|
||||
16
libs/confy/src/utils.rs
Normal file
16
libs/confy/src/utils.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
//! Some storage utilities
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Error as IoError, Read};
|
||||
|
||||
pub trait CheckedStringRead {
|
||||
fn get_string(&mut self) -> Result<String, IoError>;
|
||||
}
|
||||
|
||||
impl CheckedStringRead for File {
|
||||
fn get_string(&mut self) -> Result<String, IoError> {
|
||||
let mut s = String::new();
|
||||
self.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ rand = "0.7"
|
||||
serde_derive = "1.0"
|
||||
serde = "1.0"
|
||||
lazy_static = "1.4"
|
||||
confy = { git = "https://github.com/open-trade/confy" }
|
||||
confy = { path = "../confy" }
|
||||
dirs-next = "2.0"
|
||||
filetime = "0.2"
|
||||
sodiumoxide = "0.2"
|
||||
|
||||
Reference in New Issue
Block a user