s/toml_config/aquatic_toml_config/

This commit is contained in:
Joakim Frostegård 2022-02-19 15:11:00 +01:00
parent 8abdf702b7
commit 14a4c10546
27 changed files with 77 additions and 77 deletions

View file

@ -0,0 +1,21 @@
[package]
name = "aquatic_toml_config"
version = "0.1.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "WebTorrent tracker protocol"
repository = "https://github.com/greatest-ape/aquatic"
exclude = ["target"]
[lib]
name = "aquatic_toml_config"
[dependencies]
toml = "0.5"
aquatic_toml_config_derive = { path = "../aquatic_toml_config_derive" }
[dev-dependencies]
serde = { version = "1.0", features = ["derive"] }
quickcheck = "1"
quickcheck_macros = "1"

View file

@ -0,0 +1,126 @@
pub use toml;
pub use aquatic_toml_config_derive::TomlConfig;
/// Run this on your struct implementing TomlConfig to generate a
/// serialization/deserialization test for it.
#[macro_export]
macro_rules! gen_serialize_deserialize_test {
($ident:ident) => {
#[test]
fn test_cargo_toml_serialize_deserialize() {
use ::aquatic_toml_config::TomlConfig;
let serialized = $ident::default_to_string();
let deserialized = ::aquatic_toml_config::toml::de::from_str(&serialized).unwrap();
assert_eq!($ident::default(), deserialized);
}
};
}
/// Export structs to toml, converting Rust doc strings to comments.
///
/// Supports one level of nesting. Fields containing structs must come
/// after regular fields.
///
/// Usage:
/// ```
/// use aquatic_toml_config::TomlConfig;
///
/// #[derive(TomlConfig)]
/// struct SubConfig {
/// /// A
/// a: usize,
/// /// B
/// b: String,
/// }
///
/// impl Default for SubConfig {
/// fn default() -> Self {
/// Self {
/// a: 200,
/// b: "subconfig hello".into(),
/// }
/// }
/// }
///
/// #[derive(TomlConfig)]
/// struct Config {
/// /// A
/// a: usize,
/// /// B
/// b: String,
/// /// C
/// c: SubConfig,
/// }
///
/// impl Default for Config {
/// fn default() -> Self {
/// Self {
/// a: 100,
/// b: "hello".into(),
/// c: Default::default(),
/// }
/// }
/// }
///
/// let expected = "# A\na = 100\n# B\nb = \"hello\"\n\n# C\n[c]\n# A\na = 200\n# B\nb = \"subconfig hello\"\n";
///
/// assert_eq!(
/// Config::default_to_string(),
/// expected,
/// );
/// ```
pub trait TomlConfig: Default {
fn default_to_string() -> String;
}
pub mod __private {
use std::net::SocketAddr;
use std::path::PathBuf;
pub trait Private {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String;
}
macro_rules! impl_trait {
($ident:ident) => {
impl Private for $ident {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String {
let mut output = String::new();
if let Some(comment) = comment {
output.push_str(&comment);
}
let value = crate::toml::ser::to_string(self).unwrap();
output.push_str(&format!("{} = {}\n", field_name, value));
output
}
}
};
}
impl_trait!(isize);
impl_trait!(i8);
impl_trait!(i16);
impl_trait!(i32);
impl_trait!(i64);
impl_trait!(usize);
impl_trait!(u8);
impl_trait!(u16);
impl_trait!(u32);
impl_trait!(u64);
impl_trait!(f32);
impl_trait!(f64);
impl_trait!(bool);
impl_trait!(String);
impl_trait!(PathBuf);
impl_trait!(SocketAddr);
}

View file

@ -0,0 +1,46 @@
use serde::Deserialize;
use aquatic_toml_config::{gen_serialize_deserialize_test, TomlConfig};
#[derive(Clone, Debug, PartialEq, Eq, TomlConfig, Deserialize)]
struct TestConfigInnerA {
/// Comment for a
a: String,
/// Comment for b
b: usize,
}
impl Default for TestConfigInnerA {
fn default() -> Self {
Self {
a: "Inner hello world".into(),
b: 100,
}
}
}
/// Comment for TestConfig
#[derive(Clone, Debug, PartialEq, Eq, TomlConfig, Deserialize)]
struct TestConfig {
/// Comment for a that stretches over
/// multiple lines
a: String,
/// Comment for b
b: usize,
c: bool,
/// Comment for TestConfigInnerA
inner_a: TestConfigInnerA,
}
impl Default for TestConfig {
fn default() -> Self {
Self {
a: "Hello, world!".into(),
b: 100,
c: true,
inner_a: Default::default(),
}
}
}
gen_serialize_deserialize_test!(TestConfig);